Submission #216316

#TimeUsernameProblemLanguageResultExecution timeMemory
216316model_codeHarvest (JOI20_harvest)C++17
100 / 100
1183 ms100932 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>

class Segment_Tree{
	public:
	int n;
	std::vector<long long> data;
	void Init(int n_){
		n=1;
		while(n<n_) n*=2;
		data=std::vector<long long>(2*n-1);
	}
	void Update(int k){
		k+=n-1;
		data[k]++;
		while(k>0){
			k=(k-1)/2;
			data[k]=data[k*2+1]+data[k*2+2];
		}
	}
	long long Query(int a,int b){
		a+=n-1;b+=n-1;
		long long m=0;
		while(a<b){
			if(a%2==0) m+=data[a++];
			if(b%2==0) m+=data[--b];
			a/=2;b/=2;
		}
		return m;
	}
};

int N,M,L,C,Q;
std::vector<int> A;

std::vector<int> nx,right;
std::vector<std::vector<int>> rev;
std::vector<long long> cost;
std::vector<std::vector<long long>> a;
std::vector<std::vector<std::pair<long long,int>>> c;

void dfs(int v,long long dep,int rt,int &id,std::vector<std::pair<long long,std::pair<int,int>>> &query){
	int pre=id;
	for(auto i:a[v]){
		a[nx[rt]].push_back(i+dep+cost[rt]);
		query.push_back(std::make_pair(i+dep,std::make_pair(-1,id)));
	}
	for(auto p:c[v]) query.push_back(std::make_pair(p.first+dep,std::make_pair(p.second,id)));
	for(auto u:rev[v]){
		id++;
		dfs(u,dep+cost[u],rt,id,query);
	}
	right[pre]=id;
}

int main(){
	scanf("%d%d%d%d",&N,&M,&L,&C);
	A=std::vector<int>(N);
	for(int i=0;i<N;i++) scanf("%d",&A[i]);
	int id=0;
	right=nx=std::vector<int>(N);
	rev=std::vector<std::vector<int>>(N);
	cost=std::vector<long long>(N);
	a=std::vector<std::vector<long long>>(N);
	std::vector<int> deg(N),vis(N);
	for(int i=0;i<N;i++){
		int x=(A[i]-C%L+L)%L;
		auto it=std::upper_bound(A.begin(),A.end(),x);
		nx[i]=(it==A.begin()?N-1:it-A.begin()-1);
		rev[nx[i]].push_back(i);
		cost[i]=C+(x-A[nx[i]]+L)%L;
		deg[nx[i]]++;
	}
	std::queue<int> que;
	for(int i=0;i<N;i++) if(!deg[i]) que.push(i);
	while(!que.empty()){
		int v=que.front(),u=nx[v];
		que.pop();
		deg[u]--;
		if(!deg[u]) que.push(u);
	}
	for(int i=0;i<M;i++){
		int x;
		scanf("%d",&x);
		while(id<N&&A[id]<x) id++;
		int v=(id-1+N)%N;
		long long t=(x-A[v]+L)%L;
		a[v].push_back(t);
	}
	scanf("%d",&Q);
	std::vector<long long> res(Q);
	c=std::vector<std::vector<std::pair<long long,int>>>(N);
	for(int i=0;i<Q;i++){
		int v;
		long long t;
		scanf("%d%lld",&v,&t);
		v--;
		c[v].push_back(std::make_pair(t,i));
	}
	for(int i=0;i<N;i++) if(!vis[i]&&deg[i]){
		int v=i;
		long long cycle=0,dis=0;
		Segment_Tree st;
		do{
			cycle+=cost[v];
			vis[v]++;
			for(auto j:rev[v]) if(!deg[j]){
				std::vector<std::pair<long long,std::pair<int,int>>> query;
				int sz=0;
				dfs(j,0,j,sz,query);
				std::sort(query.begin(),query.end());
				st.Init(sz+1);
				for(auto pp:query){
					auto p=pp.second;
					int ind=p.second;
					if(p.first>=0) res[p.first]=st.Query(ind,right[ind]+1);
					else st.Update(ind);
				}
			}
			v=nx[v];
		}while(v!=i);
		std::vector<std::pair<long long,int>> query;
		std::vector<long long> b;
		std::map<long long,int> mp;
		do{
			for(auto j:a[v]){
				query.push_back(std::make_pair(j-dis+cycle,-1));
				b.push_back((j-dis+cycle)%cycle);
			}
			for(auto p:c[v]) if(p.first>=dis){
				query.push_back(std::make_pair(p.first-dis,p.second));
				b.push_back((p.first-dis)%cycle);
			}
			dis+=cost[v];
			v=nx[v];
		}while(v!=i);
		std::sort(query.begin(),query.end());
		std::sort(b.begin(),b.end());
		b.erase(std::unique(b.begin(),b.end()),b.end());
		int sz=b.size();
		for(int i=0;i<sz;i++) mp[b[i]]=i;
		st.Init(sz);
		long long sum=0;
		for(auto p:query){
			int j=mp[p.first%cycle];
			long long tmp=p.first/cycle;
			if(p.second>=0) res[p.second]=st.Query(0,j+1)*(tmp+1)+st.Query(j+1,sz)*tmp-sum;
			else{
				st.Update(j);
				sum+=tmp;
			}
		}
		b.clear();
		mp.clear();
		dis=0;
		do{
			for(auto j:a[v]) b.push_back(j-dis);
			for(auto p:c[v]) b.push_back(p.first-dis);
			dis+=cost[v];
			v=nx[v];
		}while(v!=i);
		std::sort(b.begin(),b.end());
		b.erase(std::unique(b.begin(),b.end()),b.end());
		sz=b.size();
		for(int i=0;i<sz;i++) mp[b[i]]=i;
		st.Init(sz);
		dis=0;
		do{
			for(auto j:a[v]) st.Update(mp[j-dis]);
			for(auto p:c[v]){
				res[p.second]+=st.Query(0,mp[p.first-dis]+1);
			}
			dis+=cost[v];
			v=nx[v];
		}while(v!=i);
	}
	for(int i=0;i<Q;i++) printf("%lld\n",res[i]);
}

Compilation message (stderr)

harvest.cpp: In function 'int main()':
harvest.cpp:60:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d%d%d",&N,&M,&L,&C);
  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
harvest.cpp:62:28: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for(int i=0;i<N;i++) scanf("%d",&A[i]);
                       ~~~~~^~~~~~~~~~~~
harvest.cpp:87:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d",&x);
   ~~~~~^~~~~~~~~
harvest.cpp:93:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d",&Q);
  ~~~~~^~~~~~~~~
harvest.cpp:99:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%lld",&v,&t);
   ~~~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...