[BZOJ3932][CQOI2015]任务查询系统(差分+主席树)
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ3932][CQOI2015]任务查询系统(差分+主席树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題面
分析
對于一個區間修改(s,e,v),我們可以將它差分,這樣就變成了單點修改s和e+1(s插入,t+1刪除)
我們用主席樹維護差分數組的前綴和,第i棵主席樹維護區間[1,i]之間的所有差分值
那么查詢我們直接在第i棵主席樹里查第k大即可
注意:
1.主席樹里面要維護兩個值,一個是值落在區間[l,r]內的樹的個數cnt,一個是這cnt個數的和
2.注意有多個數相同的情況,查詢到葉子節點[l,l]之后,不能直接返回sum,而是應該返回k*b[l],其中b[l]是l離散化之前的值
這里有一組hack數據
in: 3 3 1 1 1 1 2 1 1 3 1 1 0 1 100 2 0 1 100 3 0 1 100rightout: 2 2 1代碼
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxn 300005 #define maxlogn 21 using namespace std; int m,n; vector<int>d[maxn]; int b[maxn]; int sz;struct node{ #ifdef DEBUGint l;int r; #endifint ls;int rs;int cnt;long long sum; }tree[2*maxn*maxlogn]; int root[maxn*2]; int ptr; void push_up(int pos){tree[pos].cnt=tree[tree[pos].ls].cnt+tree[tree[pos].rs].cnt;tree[pos].sum=tree[tree[pos].ls].sum+tree[tree[pos].rs].sum; } void update(int &pos,int last,int upos,int uval,int flag,int l,int r){pos=++ptr;tree[pos]=tree[last]; #ifdef DEBUGtree[pos].l=l;tree[pos].r=r; #endifif(l==r){tree[pos].cnt+=flag;tree[pos].sum+=uval*flag;return;}int mid=(l+r)>>1;if(upos<=mid) update(tree[pos].ls,tree[last].ls,upos,uval,flag,l,mid);else update(tree[pos].rs,tree[last].rs,upos,uval,flag,mid+1,r);push_up(pos); }long long query(int ql,int qr,int qk,int l,int r){if(l==r){//注意多組數據相同的情況,必須要用k*值,不能用sum//見最下方hack數據 return b[l]*qk;}int mid=(l+r)>>1;int lcnt=tree[tree[qr].ls].cnt-tree[tree[ql].ls].cnt;if(qk<=lcnt) return query(tree[ql].ls,tree[qr].ls,qk,l,mid);else return tree[tree[qr].ls].sum-tree[tree[ql].ls].sum+query(tree[ql].rs,tree[qr].rs,qk-lcnt,mid+1,r); }int main(){int s,e,v;long long xx,aa,bb,cc;scanf("%d %d",&m,&n);for(int i=1;i<=m;i++){scanf("%d %d %d",&s,&e,&v);d[s].push_back(v);d[e+1].push_back(-v);b[++sz]=v;}sort(b+1,b+1+sz);sz=unique(b+1,b+1+sz)-b-1;for(int i=1;i<=n;i++){root[i]=root[i-1];for(int j=0;j<d[i].size();j++){int val=d[i][j];//正數代表插入,負數代表刪除int disval=lower_bound(b+1,b+1+sz,abs(val))-b;if(val<0) update(root[i],root[i],disval,abs(val),-1,1,sz);else update(root[i],root[i],disval,abs(val),1,1,sz);}} long long ans=1;for(int i=1;i<=n;i++){scanf("%lld %lld %lld %lld",&xx,&aa,&bb,&cc);long long k=1+(aa*ans+bb)%cc;if(k>tree[root[xx]].cnt) ans=tree[root[xx]].sum;else ans=query(root[0],root[xx],k,1,sz);printf("%lld\n",ans);} }轉載于:https://www.cnblogs.com/birchtree/p/10851751.html
總結
以上是生活随笔為你收集整理的[BZOJ3932][CQOI2015]任务查询系统(差分+主席树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot 2.x (12):
- 下一篇: java信息管理系统总结_java实现科