Submission #297685

#TimeUsernameProblemLanguageResultExecution timeMemory
297685cfalasHorses (IOI15_horses)C++14
57 / 100
1571 ms95720 KiB
#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#include<bits/stdc++.h>
#include "horses.h"
using namespace std;

#define FORi(i,a,b) for(int i=a;i<b;i++)
#define MOD 1000000007
#define FOR(i,n) FORi(i,0,n)

#define ll long long
#define MID ((l+r)/2)
#define len(x) ((int)((x).size()))

template<typename T>
struct seg_tree{
	struct node{
		T val;
		T laz;
		int left=-1;
		int right=-1;
		node() {val=0, laz=0, left=-1, right=-1;}
		node(T v) {val=v, laz=0, right=-1, left=-1;}
	};
	vector<node> seg;
	static inline int N;
	const int RAND_VALUE=1;
	seg_tree(int n){N=n, seg.assign(1, node());}
	seg_tree(){seg.assign(1, node());}

	inline node merge(node par, node a, node b){
		node ret;
		ret.left = par.left, ret.right = par.right;
		ret.val = max(a.val , b.val);
		return ret;
	}

	inline void update_node(int ind, int val, int l, int r){
		seg[ind].val = val;
	}

	inline void create_children(int ind){
		node par = seg[ind];
		if(par.left==-1){
			//cout<<"left\n";
			par.left=seg.size(), seg.push_back(node());
		}
		if(par.right==-1) par.right=seg.size(), seg.push_back(node());
		seg[ind] = par;
	}

	void build(vector<T>& arr, int l=0, int r=N-1, int ind=0){
		if(l==r) seg[ind] = node(arr[l]);
		else{
			create_children(ind);
			build(arr,l,MID,seg[ind].left);
			build(arr,MID+1,r,seg[ind].right);

			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	void update(int rl, int rr, int val, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) update_node(ind, val,l,r);
		else if(rr<l || r<rl) return;
		else{
			create_children(ind);
			update(rl,rr,val,l,MID,seg[ind].left);
			update(rl,rr,val,MID+1,r,seg[ind].right);
			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	node _query(int rl, int rr, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) return seg[ind];
		else if(rl>r || l>rr) return RAND_VALUE;
		else{
			create_children(ind);
			return merge(seg[ind], _query(rl, rr, l, MID, seg[ind].left), _query(rl,rr,MID+1,r,seg[ind].right));
		}
	}

	T query(int l, int r){
		return _query(l,r).val;
	}
	
};

template<typename T>
struct mult_seg_tree{
	struct node{
		T val;
		T laz;
		int left=-1;
		int right=-1;
		node() {val=1, laz=0, left=-1, right=-1;}
		node(T v) {val=v, laz=0, right=-1, left=-1;}
	};
	vector<node> seg;
	static inline int N;
	const int RAND_VALUE=1;
	mult_seg_tree(int n){N=n, seg.assign(1, node());}
	mult_seg_tree(){seg.assign(1, node());}

	inline node merge(node par, node a, node b){
		node ret;
		ret.left = par.left, ret.right = par.right;
		ret.val = a.val * b.val;
		return ret;
	}

	inline void update_node(int ind, int val, int l, int r){
		seg[ind].val = val;
	}

	inline void down(node &par, int l, int r){
		/*
		seg[par.left].val += par.laz * (MID-l+1);
		seg[par.right].val += par.laz * (r-MID);

		seg[par.left].laz = par.laz;
		seg[par.right].laz = par.laz;

		par.laz = 0;
		*/
	}

	inline void create_children(int ind){
		node par = seg[ind];
		if(par.left==-1){
			//cout<<"left\n";
			par.left=seg.size(), seg.push_back(node());
		}
		if(par.right==-1) par.right=seg.size(), seg.push_back(node());
		seg[ind] = par;
	}

	void build(vector<T>& arr, int l=0, int r=N-1, int ind=0){
		if(l==r) seg[ind] = node(arr[l]);
		else{
			create_children(ind);
			build(arr,l,MID,seg[ind].left);
			build(arr,MID+1,r,seg[ind].right);

			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	void update(int rl, int rr, int val, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) update_node(ind, val,l,r);
		else if(rr<l || r<rl) return;
		else{
			create_children(ind);
			down(seg[ind],l,r);
			update(rl,rr,val,l,MID,seg[ind].left);
			update(rl,rr,val,MID+1,r,seg[ind].right);
			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	node _query(int rl, int rr, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) return seg[ind];
		else if(rl>r || l>rr) return RAND_VALUE;
		else{
			create_children(ind);
			down(seg[ind],l,r);
			return merge(seg[ind], _query(rl, rr, l, MID, seg[ind].left), _query(rl,rr,MID+1,r,seg[ind].right));
		}
	}

	T query(int l, int r){
		return _query(l,r).val;
	}
	
};

template<typename T>
struct mult_mod_seg_tree{
	struct node{
		T val;
		T laz;
		int left=-1;
		int right=-1;
		node() {val=0, laz=0, left=-1, right=-1;}
		node(T v) {val=v, laz=0, right=-1, left=-1;}
	};
	vector<node> seg;
	static inline int N;
	const int RAND_VALUE=1;
	mult_mod_seg_tree(int n){N=n, seg.assign(1, node());}
	mult_mod_seg_tree(){seg.assign(1, node());}

	inline node merge(node par, node a, node b){
		node ret;
		ret.left = par.left, ret.right = par.right;
		a.val%=MOD;
		b.val%=MOD;
		ret.val = (((ll)a.val * ((ll)b.val))) % MOD;
		return ret;
	}

	inline void update_node(int ind, int val, int l, int r){
		seg[ind].val = val;
	}

	inline void down(node &par, int l, int r){
		/*
		seg[par.left].val += par.laz * (MID-l+1);
		seg[par.right].val += par.laz * (r-MID);

		seg[par.left].laz = par.laz;
		seg[par.right].laz = par.laz;

		par.laz = 0;
		*/
	}

	inline void create_children(int ind){
		node par = seg[ind];
		if(par.left==-1){
			//cout<<"left\n";
			par.left=seg.size(), seg.push_back(node());
		}
		if(par.right==-1) par.right=seg.size(), seg.push_back(node());
		seg[ind] = par;
	}

	void build(vector<T>& arr, int l=0, int r=N-1, int ind=0){
		if(l==r) seg[ind] = node(arr[l]);
		else{
			create_children(ind);
			build(arr,l,MID,seg[ind].left);
			build(arr,MID+1,r,seg[ind].right);

			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	void update(int rl, int rr, int val, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) update_node(ind, val,l,r);
		else if(rr<l || r<rl) return;
		else{
			create_children(ind);
			down(seg[ind],l,r);
			update(rl,rr,val,l,MID,seg[ind].left);
			update(rl,rr,val,MID+1,r,seg[ind].right);
			seg[ind] = merge(seg[ind], seg[seg[ind].left], seg[seg[ind].right]);
		}
	}

	node _query(int rl, int rr, int l=0, int r=N-1, int ind=0){
		if(rl<=l && r<=rr) return seg[ind];
		else if(rl>r || l>rr) return RAND_VALUE;
		else{
			create_children(ind);
			down(seg[ind],l,r);
			return merge(seg[ind], _query(rl, rr, l, MID, seg[ind].left), _query(rl,rr,MID+1,r,seg[ind].right));
		}
	}

	T query(int l, int r){
		return _query(l,r).val%MOD;
	}

};

typedef vector<int> vi;
vi x;
vector<int> y;
vector<double> a;
set<int> xx;

clock_t start_timer;
void time_start(){
	start_timer = clock();
}
void time_end(){
	auto endt = clock();
	cout<<(double)(endt-start_timer) / CLOCKS_PER_SEC<<endl;
}

seg_tree<int> yseg;
mult_seg_tree<double> xsegd;
mult_mod_seg_tree<int> xsegm;
#define FOA(v,qq) for(auto v : qq)
int get_ans(){
	auto it = xx.end();
	it--;
	it--;
	int cnt=0;
	double maxa=0;
	int maxapos=-1, next=-1;

	// O(30)
	auto itt = xx.end();
	int cntt=0;
	while(itt!=xx.begin() && cntt<31) itt--, cntt++;

	int f = *itt;
	// O(30logN)
	while(cnt<30){
		auto it2 = it;
		it2++;
		// O(logN)
		double c = xsegd.query(f, *it);
		assert(c>0);

		// O(logN)
		c*=(double)yseg.query(*it, *it2-1);
		//cout<<c<<endl;
		if(c>maxa){
			maxa = c;
			maxapos = *it;
			next = *it2;
		}
		cnt++;
		if(it==xx.begin()) break;
		it--;
	}
	// O(logN)
	int c = xsegm.query(0, maxapos);
	c= ((ll) c * (ll) yseg.query(maxapos, next-1) ) %MOD;
	return c;
}


vector<double> dx;
int init(int N, int X[], int Y[]) {
	dx.resize(N);
	x.resize(N);
	y.resize(N);
	FOR(i,N) x[i] = X[i];
	FOR(i,N) dx[i] = X[i];
	FOR(i,N) y[i] = Y[i];

	yseg.N = N;
	yseg.build(y);

	xsegd.N = N;
	xsegd.build(dx);

	xsegm.N = N;
	xsegm.build(x);

	FOR(i,N){
		if(x[i]>1) xx.insert(i);
	}
	xx.insert(N);
	xx.insert(0);
	get_ans();
	return get_ans();
}

int cc=0;
int updateX(int pos, int val) {	
	cc++;
	if(x[pos]==val) return get_ans();
	if(val==1 && x[pos]!=1){
		xx.erase(pos);
	}
	else if(x[pos]==1 && val!=1) xx.insert(pos);
	x[pos] = val;
	dx[pos] = val;
	xsegd.update(pos, pos, dx[pos]);
	xsegm.update(pos, pos, x[pos]);
	int anss = get_ans();
	return anss;
}

int updateY(int pos, int val) {
	cc++;
	yseg.update(pos, pos, val);
	y[pos] = val;
	int anss = get_ans();
	return anss;
}

Compilation message (stderr)

horses.cpp:2: warning: ignoring #pragma GCC optimization [-Wunknown-pragmas]
    2 | #pragma GCC optimization("O3")
      | 
horses.cpp:26:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
   26 |  static inline int N;
      |         ^~~~~~
horses.cpp:100:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
  100 |  static inline int N;
      |         ^~~~~~
horses.cpp:188:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
  188 |  static inline int N;
      |         ^~~~~~
horses.cpp: In function 'int get_ans()':
horses.cpp:322:50: warning: conversion from 'long long int' to 'int' may change value [-Wconversion]
  322 |  c= ((ll) c * (ll) yseg.query(maxapos, next-1) ) %MOD;
      |                                                  ^
horses.cpp: In function 'int updateX(int, int)':
horses.cpp:364:32: warning: conversion from '__gnu_cxx::__alloc_traits<std::allocator<double>, double>::value_type' {aka 'double'} to 'int' may change value [-Wfloat-conversion]
  364 |  xsegd.update(pos, pos, dx[pos]);
      |                                ^
horses.cpp: In instantiation of 'void seg_tree<T>::create_children(int) [with T = int]':
horses.cpp:55:4:   required from 'void seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:337:14:   required from here
horses.cpp:46:12: warning: conversion from 'std::vector<seg_tree<int>::node, std::allocator<seg_tree<int>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
   46 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:48:30: warning: conversion from 'std::vector<seg_tree<int>::node, std::allocator<seg_tree<int>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
   48 |   if(par.right==-1) par.right=seg.size(), seg.push_back(node());
horses.cpp: In instantiation of 'void mult_seg_tree<T>::create_children(int) [with T = double]':
horses.cpp:141:4:   required from 'void mult_seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = double]'
horses.cpp:340:16:   required from here
horses.cpp:132:12: warning: conversion from 'std::vector<mult_seg_tree<double>::node, std::allocator<mult_seg_tree<double>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
  132 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:134:30: warning: conversion from 'std::vector<mult_seg_tree<double>::node, std::allocator<mult_seg_tree<double>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
  134 |   if(par.right==-1) par.right=seg.size(), seg.push_back(node());
horses.cpp: In instantiation of 'void mult_mod_seg_tree<T>::create_children(int) [with T = int]':
horses.cpp:231:4:   required from 'void mult_mod_seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:343:15:   required from here
horses.cpp:222:12: warning: conversion from 'std::vector<mult_mod_seg_tree<int>::node, std::allocator<mult_mod_seg_tree<int>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
  222 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:224:30: warning: conversion from 'std::vector<mult_mod_seg_tree<int>::node, std::allocator<mult_mod_seg_tree<int>::node> >::size_type' {aka 'long unsigned int'} to 'int' may change value [-Wconversion]
  224 |   if(par.right==-1) par.right=seg.size(), seg.push_back(node());
horses.cpp: In instantiation of 'mult_mod_seg_tree<T>::node mult_mod_seg_tree<T>::merge(mult_mod_seg_tree<T>::node, mult_mod_seg_tree<T>::node, mult_mod_seg_tree<T>::node) [with T = int]':
horses.cpp:235:15:   required from 'void mult_mod_seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:343:15:   required from here
horses.cpp:198:41: warning: conversion from 'long long int' to 'int' may change value [-Wconversion]
  198 |   ret.val = (((ll)a.val * ((ll)b.val))) % MOD;
      |                                         ^
horses.cpp: In instantiation of 'void mult_seg_tree<T>::update_node(int, int, int, int) [with T = double]':
horses.cpp:150:22:   required from 'void mult_seg_tree<T>::update(int, int, int, int, int, int) [with T = double]'
horses.cpp:364:32:   required from here
horses.cpp:112:48: warning: unused parameter 'l' [-Wunused-parameter]
  112 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:112:55: warning: unused parameter 'r' [-Wunused-parameter]
  112 |  inline void update_node(int ind, int val, int l, int r){
      |                                                   ~~~~^
horses.cpp: In instantiation of 'void mult_seg_tree<T>::down(mult_seg_tree<T>::node&, int, int) [with T = double]':
horses.cpp:154:4:   required from 'void mult_seg_tree<T>::update(int, int, int, int, int, int) [with T = double]'
horses.cpp:364:32:   required from here
horses.cpp:116:25: warning: unused parameter 'par' [-Wunused-parameter]
  116 |  inline void down(node &par, int l, int r){
      |                   ~~~~~~^~~
horses.cpp:116:34: warning: unused parameter 'l' [-Wunused-parameter]
  116 |  inline void down(node &par, int l, int r){
      |                              ~~~~^
horses.cpp:116:41: warning: unused parameter 'r' [-Wunused-parameter]
  116 |  inline void down(node &par, int l, int r){
      |                                     ~~~~^
horses.cpp: In instantiation of 'void mult_mod_seg_tree<T>::update_node(int, int, int, int) [with T = int]':
horses.cpp:240:22:   required from 'void mult_mod_seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:365:31:   required from here
horses.cpp:202:48: warning: unused parameter 'l' [-Wunused-parameter]
  202 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:202:55: warning: unused parameter 'r' [-Wunused-parameter]
  202 |  inline void update_node(int ind, int val, int l, int r){
      |                                                   ~~~~^
horses.cpp: In instantiation of 'void mult_mod_seg_tree<T>::down(mult_mod_seg_tree<T>::node&, int, int) [with T = int]':
horses.cpp:244:4:   required from 'void mult_mod_seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:365:31:   required from here
horses.cpp:206:25: warning: unused parameter 'par' [-Wunused-parameter]
  206 |  inline void down(node &par, int l, int r){
      |                   ~~~~~~^~~
horses.cpp:206:34: warning: unused parameter 'l' [-Wunused-parameter]
  206 |  inline void down(node &par, int l, int r){
      |                              ~~~~^
horses.cpp:206:41: warning: unused parameter 'r' [-Wunused-parameter]
  206 |  inline void down(node &par, int l, int r){
      |                                     ~~~~^
horses.cpp: In instantiation of 'void seg_tree<T>::update_node(int, int, int, int) [with T = int]':
horses.cpp:64:22:   required from 'void seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:372:27:   required from here
horses.cpp:38:48: warning: unused parameter 'l' [-Wunused-parameter]
   38 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:38:55: warning: unused parameter 'r' [-Wunused-parameter]
   38 |  inline void update_node(int ind, int val, int l, int r){
      |                                                   ~~~~^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...