Submission #297697

#TimeUsernameProblemLanguageResultExecution timeMemory
297697cfalasHorses (IOI15_horses)C++14
57 / 100
1559 ms87316 KiB
#pragma GCC optimize("Ofast")
#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<int>& 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;
		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();
	ll pp=1;
	auto st = it;
	auto vv = yseg.query(0,yseg.N-1);
	while(itt!=xx.begin() && pp<vv) itt--, pp*=x[*itt], st=itt;

	int f = *itt;
	// O(30logN)
	while(1){
		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==st) break;
		it--;
	}
	// O(logN)
	int c = xsegm.query(0, maxapos);
	c= ((ll) c * (ll) yseg.query(maxapos, next-1) ) %MOD;
	return c;
}


int init(int N, int X[], int Y[]) {
	time_start();
	x.resize(N+1);
	y.resize(N);
	FOR(i,N) x[i] = X[i], y[i] = Y[i];
	x[N] = 1;

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

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

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

	FOR(i,N){
		if(x[i]>1) xx.insert(i);
	}
	xx.insert(N);
	xx.insert(0);
	time_end();
	time_start();
	get_ans();
	time_end();
	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;
	xsegd.update(pos, pos, x[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:25:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
   25 |  static inline int N;
      |         ^~~~~~
horses.cpp:99:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
   99 |  static inline int N;
      |         ^~~~~~
horses.cpp:187:9: warning: inline variables are only available with '-std=c++17' or '-std=gnu++17'
  187 |  static inline int N;
      |         ^~~~~~
horses.cpp: In function 'void time_end()':
horses.cpp:275:7: warning: unused variable 'endt' [-Wunused-variable]
  275 |  auto endt = clock();
      |       ^~~~
horses.cpp: In function 'int get_ans()':
horses.cpp:321:50: warning: conversion from 'long long int' to 'int' may change value [-Wconversion]
  321 |  c= ((ll) c * (ll) yseg.query(maxapos, next-1) ) %MOD;
      |                                                  ^
horses.cpp: In instantiation of 'void seg_tree<T>::create_children(int) [with T = int]':
horses.cpp:54:4:   required from 'void seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:334:14:   required from here
horses.cpp:45: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]
   45 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:47: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]
   47 |   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:140:4:   required from 'void mult_seg_tree<T>::build(std::vector<int>&, int, int, int) [with T = double]'
horses.cpp:337:15:   required from here
horses.cpp:131: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]
  131 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:133: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]
  133 |   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:228:4:   required from 'void mult_mod_seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:340:15:   required from here
horses.cpp:219: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]
  219 |    par.left=seg.size(), seg.push_back(node());
horses.cpp:221: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]
  221 |   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:232:15:   required from 'void mult_mod_seg_tree<T>::build(std::vector<_Tp>&, int, int, int) [with T = int]'
horses.cpp:340:15:   required from here
horses.cpp:195:41: warning: conversion from 'long long int' to 'int' may change value [-Wconversion]
  195 |   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:149:22:   required from 'void mult_seg_tree<T>::update(int, int, int, int, int, int) [with T = double]'
horses.cpp:361:31:   required from here
horses.cpp:111:48: warning: unused parameter 'l' [-Wunused-parameter]
  111 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:111:55: warning: unused parameter 'r' [-Wunused-parameter]
  111 |  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:153:4:   required from 'void mult_seg_tree<T>::update(int, int, int, int, int, int) [with T = double]'
horses.cpp:361:31:   required from here
horses.cpp:115:25: warning: unused parameter 'par' [-Wunused-parameter]
  115 |  inline void down(node &par, int l, int r){
      |                   ~~~~~~^~~
horses.cpp:115:34: warning: unused parameter 'l' [-Wunused-parameter]
  115 |  inline void down(node &par, int l, int r){
      |                              ~~~~^
horses.cpp:115:41: warning: unused parameter 'r' [-Wunused-parameter]
  115 |  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:237:22:   required from 'void mult_mod_seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:362:31:   required from here
horses.cpp:199:48: warning: unused parameter 'l' [-Wunused-parameter]
  199 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:199:55: warning: unused parameter 'r' [-Wunused-parameter]
  199 |  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:241:4:   required from 'void mult_mod_seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:362:31:   required from here
horses.cpp:203:25: warning: unused parameter 'par' [-Wunused-parameter]
  203 |  inline void down(node &par, int l, int r){
      |                   ~~~~~~^~~
horses.cpp:203:34: warning: unused parameter 'l' [-Wunused-parameter]
  203 |  inline void down(node &par, int l, int r){
      |                              ~~~~^
horses.cpp:203:41: warning: unused parameter 'r' [-Wunused-parameter]
  203 |  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:63:22:   required from 'void seg_tree<T>::update(int, int, int, int, int, int) [with T = int]'
horses.cpp:369:27:   required from here
horses.cpp:37:48: warning: unused parameter 'l' [-Wunused-parameter]
   37 |  inline void update_node(int ind, int val, int l, int r){
      |                                            ~~~~^
horses.cpp:37:55: warning: unused parameter 'r' [-Wunused-parameter]
   37 |  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...