Bzoj3932--Cqoi2015任务查询系统
按时间来建一棵主席树
下一个时间和上一个时间的改变就是那个时间点任务的改变
具体我们可以把任务拆成两个时间点,前一个代表加上这个数,后一个是删除这个数
代码:
#include<bits/stdc++.h> #define MAXN 100005 #define MOD 1000000007 #define LINF 100000000000000ll #define INF 1000000000 #define LL long long using namespace std; inline int _abs(int a) {return a>0?a:-a;} const int mp=10000000; struct event{ int pos,k; bool operator < (event b) const { return pos<b.pos; } inline void in(int a,int b) { pos=a;k=b; } }ev[MAXN*3]; int m,n; namespace Chairman_Tree{ const int L=0,R=1; int root[MAXN],sz; struct Node{ int s,son[2],sum; }x[MAXN*70]; void Build_Tree(int l,int r,int &now,int fr,int v,int p,bool c) { if(c) now=++sz,x[now]=x[fr]; x[now].s+=p;x[now].sum+=p*v; if(l==r) return; int mid=l+r>>1; if(v>mid) Build_Tree(mid+1,r,x[now].son[R],x[fr].son[R],v,p,x[now].son[R]==x[fr].son[R]); else Build_Tree(l,mid,x[now].son[L],x[fr].son[L],v,p,x[now].son[L]==x[fr].son[L]); } void Build(int x,int y,int p,bool c) { Build_Tree(1,mp,root[x],root[y],_abs(p),p>0?1:-1,c); } LL Query(int pos,int k) { LL ret=0; int now=root[pos],l=1,r=mp,mid; if(k>=x[now].s) return x[now].sum; while(l!=r) { mid=l+r>>1; if(x[x[now].son[L]].s<k) k-=x[x[now].son[L]].s,ret+=x[x[now].son[L]].sum,now=x[now].son[R],l=mid+1; else now=x[now].son[L],r=mid; } return ret+k*l; } } using namespace Chairman_Tree; int main() { scanf("%d%d",&m,&n); for(int a,b,c,i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); ev[(i<<1)-1].in(a,c); ev[i<<1].in(b+1,-c); } sort(ev+1,ev+1+2*m); for(int now=1,i=1;i<=n;i++) { root[i]=++sz; x[root[i]]=x[root[i-1]]; while(ev[now].pos==i) Build(i,i-1,ev[now].k,0),now++; } for(LL pos,a,b,c,pre=1,i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&pos,&a,&b,&c); a=1+(a*pre+b)%c; pre=Query(pos,a); printf("%lld\n",pre); } return 0; }