真不知道我没学主席树之前是有什么勇气说自己高级数据结构以及学的七七八八了。
这道题应该也是算是主席树的经典运用。
刚开始脑抽了,想把(S,E,P)的处理直接在线用树状数组xjb搞搞算了。写完后才意识到树状数组无法(很难?)实现区间修改。
然后想了想既然这个是一下子把所有修改都放上了直接用树状数组差分一下不就好了!
然后又深感自己制杖,为什么要用树状数组差分呢,直接开几个vector维护一下就行了。
说是修改,本质上是不带修改的主席树,很快搞完。WA,眼查,无果,跟踪,无果。
拍了几组小数组测了测,最后发现问题是这样的:以往的线段树在更新对应的权值线段树时只需要更新一个pos,而这个要更新很多个pos,就会导致一些层直接修改到以前的版本。
最后的解决办法就是对于每个点,开两个交叉更新即可。
语文不好QAQ,直接看代码比较清晰。
//BZOJ 3932 //by Cydiater //2016.12.8 #include <iostream> #include <cmath> #include <iomanip> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <map> #include <algorithm> #include <ctime> #include <bitset> #include <set> #include <vector> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define down(i,j,n) for(int i=j;i>=n;i--) #define cmax(a,b) a=max(a,b) #define cmin(a,b) a=min(a,b) #define pii pair<int,int> #define FILE "cqoi15_query" const int MAXN=1e5+5; const int oo=0x3f3f3f3f; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int N,M,fsort[MAXN],rnum=0,cnt=0,root[MAXN<<5]; ll Pre=1; struct Query{ int S,T,P; }query[MAXN]; struct Chair_man_Tree{ int tol,son[2]; ll sum; }t[MAXN<<6]; vector<pii> op[MAXN]; namespace solution{ int NewNode(int tol,ll sum,int son0,int son1){ t[++cnt].tol=tol;t[cnt].sum=sum; t[cnt].son[0]=son0;t[cnt].son[1]=son1; return cnt; } void insert(int leftt,int rightt,int &Root,int last,int pos,int flag){ Root=NewNode(t[last].tol+flag,t[last].sum+fsort[pos]*flag,t[last].son[0],t[last].son[1]); if(leftt==rightt) return; int mid=(leftt+rightt)>>1; if(pos<=mid) insert(leftt,mid,t[Root].son[0],t[last].son[0],pos,flag); else insert(mid+1,rightt,t[Root].son[1],t[last].son[1],pos,flag); } void Build(){ N=read();M=read(); up(i,1,N){ int S=read(),T=read(),P=read(); fsort[++rnum]=P; query[i]=(Query){S,T,P}; } sort(fsort+1,fsort+rnum+1); rnum=unique(fsort+1,fsort+rnum+1)-(fsort+1); up(i,1,N){ int S=query[i].S,T=query[i].T,P=query[i].P,pos=lower_bound(fsort+1,fsort+rnum+1,P)-fsort; op[S].push_back(make_pair(pos,1));op[T+1].push_back(make_pair(pos,-1)); } up(i,1,M){ int last=root[i-1],now; up(j,0,(int)op[i].size()-1){ pii tmp=op[i][j]; int pos=tmp.first,flag=tmp.second; insert(1,rnum,now,last,pos,flag); last=now; } root[i]=last; } } ll Get(int leftt,int rightt,int Root,ll rnk){ ll sum=t[Root].sum,tol=t[Root].tol; if(leftt==rightt) return min(tol,rnk)*fsort[leftt]; sum=t[t[Root].son[0]].sum;tol=t[t[Root].son[0]].tol; int mid=(leftt+rightt)>>1; if(rnk>=tol) return sum+Get(mid+1,rightt,t[Root].son[1],rnk-tol); else return Get(leftt,mid,t[Root].son[0],rnk); } void Slove(){ while(M--){ ll X,A,B,C,K; X=read();A=read();B=read();C=read(); K=1+(A*Pre+B)%C; printf("%lld\n",(Pre=Get(1,rnum,root[X],K))); } } } int main(){ //freopen("input.in","r",stdin); //freopen("out1.out","w",stdout); freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); using namespace solution; Build(); Slove(); return 0; }
时间: 2024-10-29 19:05:32