[CQOI2015]任务查询系统,洛谷P3168,主席树+差分+前缀和

正题

      一说到区间修改,单点查询,你是不是想到了树状数组的差分。

      那么既然有差分,我们就会开始思考怎么快速求前缀和。

     你一开始可能会说,你给开始那个位置加上一个k,结束的后一个位置减去一个k,然后用树状数组套主席树来维护一下不就行了emm。

     然后你知道你的复杂度是nloglogn,你超时了哈哈哈哈~

     其实中途不带修改,我们就可以直接把,当前点的信息,通过前缀和统计算出来就可以了。

     

for(int i=1;i<=n;i++){
		int x,y,k;
		scanf("%d %d %d",&x,&y,&k);
		ins(x,k,1);ins(y+1,k,-1);//相当于一个建边的过程
	}
	int L=0;
	for(int i=1;i<=n;i++){
		for(int j=first[i];j!=0;j=s[j].next){//邻接表来构建。
			d=s[j].d,v=s[j].x;
			L++;
			update(root[L-1],root[L],1,10000000);//用一个L虚拟根来模拟每次修改,用spj来记录i点真正的根
		}
		spj[i]=L;
	}

      建出来前缀树之后,我们就可以对于每个询问找对应的树就可以了,时间复杂度控制在nlogn.

代码<主要是函数写得巧妙一些,spj的概念>

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

struct edge{
	int x,d,next;
}s[300010];
int first[100010];
int n,m;
int len=0;
int ls[5000010],rs[5000010];
int c[5000010];
long long t[5000010];
int d,v;
int root[5000010];
int spj[100010];
int tot=0;

void ins(int x,int y,int c){
	len++;
	s[len].x=y;s[len].d=c;s[len].next=first[x];first[x]=len;
}

void update(int y,int&x,int l,int r){
	ls[x=++tot]=ls[y];rs[x]=rs[y];c[x]=c[y];t[x]=t[y];
	c[x]+=d;t[x]+=v*d;
	if(l==r) return ; 
	if(v<=(l+r)/2) update(ls[y],ls[x],l,(l+r)/2);
	else update(rs[y],rs[x],(l+r)/2+1,r);
}

long long solve(int x,long long k,int l,int r){
	if(l==r) return k*l;
	if(k<=c[ls[x]]) return solve(ls[x],k,l,(l+r)/2);
	else return solve(rs[x],k-c[ls[x]],(l+r)/2+1,r)+t[ls[x]];
}

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		int x,y,k;
		scanf("%d %d %d",&x,&y,&k);
		ins(x,k,1);ins(y+1,k,-1);
	}
	int L=0;
	for(int i=1;i<=n;i++){
		for(int j=first[i];j!=0;j=s[j].next){
			d=s[j].d,v=s[j].x;
			L++;
			update(root[L-1],root[L],1,10000000);
		}
		spj[i]=L;
	}
	int x;
	long long last=1;
	long long a,b,op;
	long long k;
	int rt=0;
	for(int i=1;i<=m;i++){
		scanf("%d %lld %lld %lld",&x,&a,&b,&op);
		k=1+((a%op*last%op)+b%op)%op;rt=root[spj[x]];
		printf("%lld\n",last=(c[rt]<=k?t[rt]:solve(rt,k,1,10000000)));
	}
}


猜你喜欢

转载自blog.csdn.net/deep_kevin/article/details/80487742