[CQOI2015]任務查詢系統
阿新 • • 發佈:2018-04-06
push cto 三元 span 管理 lin first c++ submit
Submit: 4329 Solved: 1428
[Submit][Status][Discuss]
輸入文件第一行包含兩個空格分開的正整數m和n,分別表示任務總數和時間範圍。接下來m行,每行包含三個空格
分開的正整數Si、Ei和Pi(Si≤Ei),描述一個任務。接下來n行,每行包含四個空格分開的整數Xi、Ai、Bi和Ci,
描述一次查詢。查詢的參數Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci計算得到。其中Pre表示上一次查詢的結果,
對於第一次查詢,Pre=1。
1 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3
8
11
3932: [CQOI2015]任務查詢系統
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4329 Solved: 1428
[Submit][Status][Discuss]
Description
最近實驗室正在為其管理的超級計算機編制一套任務管理系統,而你被安排完成其中的查詢部分。超級計算機中的 任務用三元組(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任務從第Si秒開始,在第Ei秒後結束(第Si秒和Ei秒任務也在運行 ),其優先級為Pi。同一時間可能有多個任務同時執行,它們的優先級可能相同,也可能不同。調度系統會經常向 查詢系統詢問,第Xi秒正在運行的任務中,優先級最小的Ki個任務(即將任務按照優先級從小到大排序後取前Ki個 )的優先級之和是多少。特別的,如果Ki大於第Xi秒正在運行的任務總數,則直接回答第Xi秒正在運行的任務優先 級之和。上述所有參數均為整數,時間的範圍在1到n之間(包含1和n)。Input
Output
輸出共n行,每行一個整數,表示查詢結果。Sample Input
4 31 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3
Sample Output
28
11
優秀的解法當然是主席樹了
初始值的時候加入 結束時+1刪除 然後區間求和就行了
#include <bits/stdc++.h> #define ll long long #define s second #define f first #define pii pair<ll,int> const int MAXN=1e5+10; using namespace std; typedef struct node{ int l,r,num;ll sum; }node; node d[45*MAXN]; int rt[MAXN]; vector<ll>vec;int cnt; void update(int &x,int y,int l,int r,int t,int flag){ x=++cnt;d[x]=d[y]; if(flag) d[x].num++,d[x].sum+=vec[t-1]; else d[x].num--,d[x].sum-=vec[t-1]; if(l==r) return ; int mid=(l+r)>>1; if(t<=mid) update(d[x].l,d[y].l,l,mid,t,flag); else update(d[x].r,d[y].r,mid+1,r,t,flag); } ll sum; void querty(int x,int l,int r,int k){ //cout<<l<<" "<<r<<" "<<d[x].sum<<endl; if(l==r) {sum+=vec[l-1]*k;return ;} int mid=(l+r)>>1; if(d[d[x].l].num>=k) querty(d[x].l,l,mid,k); else sum+=d[d[x].l].sum,querty(d[x].r,mid+1,r,k-d[d[x].l].num); } vector<pii>vv[MAXN]; int main(){ int n,m;scanf("%d%d",&n,&m); int l,r;ll x; for(int i=1;i<=n;i++){ scanf("%d%d%lld",&l,&r,&x); vv[l].push_back(make_pair(x,1)); vv[r+1].push_back(make_pair(x,0)); vec.push_back(x); } sort(vec.begin(),vec.end()); int t=unique(vec.begin(),vec.end())-vec.begin(); for(int i=0;i<=n+1;i++){ if(i) rt[i]=rt[i-1]; for(int j=0;j<vv[i].size();j++){ vv[i][j].f=lower_bound(vec.begin(),vec.begin()+t,vv[i][j].f)-vec.begin()+1; update(rt[i],rt[i],1,t,vv[i][j].f,vv[i][j].s);} } ll a,b,c;ll Lans=1;ll k; for(int i=1;i<=m;i++){ scanf("%d%lld%lld%lld",&x,&a,&b,&c); k=1+(a*Lans+b)%c; if(d[rt[x]].num<=k) Lans=d[rt[x]].sum; else sum=0,querty(rt[x],1,t,k),Lans=sum; printf("%lld\n",Lans); } return 0; }
擼一發可持久化treap 第一次寫這個 調了很久 最後發現wa點在查詢的時候 寫掛了!!!一直以為是持久化的地方寫錯了!!!
#include <bits/stdc++.h> #define ll long long #define s second #define f first #define pii pair<ll,int> const int MAXN=1e5+10; using namespace std; int ch[MAXN*100][2],size[MAXN*100],fst[MAXN*100]; int s[MAXN*100],cnt1; ll sum[MAXN*100],key[MAXN*100]; int rt[MAXN],cnt; vector<pii>vv[MAXN]; int newnode(ll vul){ int x; if(cnt1) x=s[cnt1--]; else x=++cnt; ch[x][0]=ch[x][1]=0;size[x]=1;key[x]=sum[x]=vul;fst[x]=rand(); return x; } int copynode(int y){ int x; if(cnt1) x=s[cnt1--]; else x=++cnt; fst[x]=fst[y]; ch[x][0]=ch[y][0];ch[x][1]=ch[y][1];key[x]=key[y];sum[x]=sum[y];size[x]=size[y]; return x; } void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];} int merge(int x,int y){ if(!x) return y; if(!y) return x; int r; if(fst[x]<=fst[y]){ r=copynode(x); ch[r][1]=merge(ch[x][1],y); up(r); return r; } else{ r=copynode(y); ch[r][0]=merge(x,ch[y][0]); up(r); return r; } } pii split(int x,int k){ if(!x) return make_pair(0,0); pii y;int r;r=copynode(x); if(size[ch[r][0]]>=k){ y=split(ch[r][0],k); ch[r][0]=y.s; up(r); y.s=r; } else{ y=split(ch[r][1],k-size[ch[r][0]]-1); //r=copynode(x); ch[r][1]=y.f; up(r); y.f=r; } return y; } int ans; void find1(int x,ll vul){ if(!x) return ; if(key[x]<=vul) ans+=(size[ch[x][0]]+1),find1(ch[x][1],vul); else find1(ch[x][0],vul); } void insert(int &x,ll vul){ ans=0;find1(x,vul); pii y1=split(x,ans); int t=newnode(vul); x=merge(merge(y1.f,t),y1.s); } void erase(int &x,int vul){ ans=0;find1(x,vul); pii y1=split(x,ans-1); pii y2=split(y1.s,1); s[++cnt1]=y2.f; x=merge(y1.f,y2.s); } ll ans1; void querty(int x,int k){ if(!x || !k) return ; if(size[ch[x][0]]+1==k) {ans1+=(key[x]+sum[ch[x][0]]);return ;} else if(size[ch[x][0]]>=k) querty(ch[x][0],k); else ans1+=(key[x]+sum[ch[x][0]]),querty(ch[x][1],k-size[ch[x][0]]-1); } int main(){ cnt=cnt1=0; int n,m;scanf("%d%d",&n,&m); int l,r;ll x; for(int i=1;i<=n;i++){ scanf("%d%d%lld",&l,&r,&x); vv[l].push_back(make_pair(x,1)); vv[r+1].push_back(make_pair(x,0)); } for(int i=0;i<=n+1;i++){ if(i) rt[i]=rt[i-1]; for(int j=0;j<vv[i].size();j++){ if(vv[i][j].s) insert(rt[i],vv[i][j].f); else erase(rt[i],vv[i][j].f); } } //for(int i=1;i<=n;i++) debug(rt[i]); ll a,b,c;ll Lans=1;ll k; for(int i=1;i<=m;i++){ scanf("%d%lld%lld%lld",&x,&a,&b,&c); k=1+(a*Lans+b)%c; if(size[rt[x]]<=k) Lans=sum[rt[x]]; else ans1=0,querty(rt[x],k),Lans=ans1; printf("%lld\n",Lans); } return 0; }
[CQOI2015]任務查詢系統