1. 程式人生 > >BZOJ 3932: [CQOI2015]任務查詢系統 | 主席樹練習題

BZOJ 3932: [CQOI2015]任務查詢系統 | 主席樹練習題

系統 習題 algo b+ col ace struct name https

題目:

洛谷也能評測


題解:

De了好長時間BUG發現是自己sort前面有一行for沒刪,氣死.

題目詢問第x秒時候前k小的P值之和.

樸素想法:

我們可以把P值離散化,然後對於每個時刻建一棵定義域是離散化後P值的線段樹

每個節點維護了這個節點代表區間的任務個數和這些任務離散化之前的P值之和,

對於每個在這個時間段的任務,插入,即在p位置單點修改

詢問就是類似二叉查找樹的寫法

高級想法:

首先把一段任務拆成兩個:添加和刪除,用三元組(t,p,d)表示,d=1表示插入,d=-1表示刪除

對於第maxt棵線段樹,我們把操作按t值排序之後進行,

這豈不是就變成可以一棵可以訪問歷史版本的線段樹---主席樹了!

那麽寫棵主席樹,插入操作按t排序就O**K了

#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll; 
#define N 200100
#define Nlogn N*20
using namespace std;
ll root[Nlogn],n,A,B,C,pre=1,m,b[N],K,pcnt,opcnt,lim;
struct node
{
    ll lc,rc,sum,val;
}t[Nlogn];
struct Op
{
    ll t,p,d;
    
bool operator < (const Op &a) const{return t<a.t;} }op[2*N]; ll read() { ll ret=0,neg=1;char j=getchar(); for (;j>9 || j<0;j=getchar()) if (j==-) neg=-1; for (;j>=0 && j<=9;j=getchar()) ret=ret*10+j-0; return ret*neg; } void Insert(ll y,ll &x,ll l,ll r,ll p,ll d) { t[x
=++pcnt]=t[y]; t[x].sum+=d;t[x].val+=b[p]*d; if (l==r) return; ll mid=l+r>>1; if (p<=mid) Insert(t[y].lc,t[x].lc,l,mid,p,d); else Insert(t[y].rc,t[x].rc,mid+1,r,p,d); } ll query(ll u,ll l,ll r,ll k) { ll mid,ret=0; while (l<r) { if (t[u].sum==0) return ret; mid=l+r>>1; if (k<=t[t[u].lc].sum) r=mid,u=t[u].lc; else k-=t[t[u].lc].sum,ret+=t[t[u].lc].val,l=mid+1,u=t[u].rc; } return ret+b[l]*k; } int getroot(int x) { return root[x-1]=(root[x-1]!=0 || x==1)?root[x-1]:getroot(x-1); } int main() { m=read(),n=read(); for (ll i=1,s,e,p;i<=m;i++) { s=read(),e=read(),p=read(); op[++opcnt].t=s,b[opcnt]=op[opcnt].p=p,op[opcnt].d=1; op[++opcnt].t=e+1,b[opcnt]=op[opcnt].p=p,op[opcnt].d=-1; } //離散化 sort(b+1,b+1+opcnt); lim=unique(b+1,b+1+opcnt)-b-1; for (ll i=1;i<=opcnt;i++) op[i].p=lower_bound(b+1,b+lim+1,op[i].p)-b; //按操作時間插入節點 sort(op+1,op+1+opcnt); for (ll i=1,j=1;i<=opcnt;i++) { if (root[op[i].t]==0) root[op[i].t]=getroot(op[i].t); Insert(root[op[i].t],root[op[i].t],1,lim+10,op[i].p,op[i].d); } for (ll i=1,x;i<=n;i++) { x=read(),A=read(),B=read(),C=read(); K=1+(A*pre+B)%C; printf("%lld\n",pre=query(root[x],1,lim+10,K)); } return 0; }

BZOJ 3932: [CQOI2015]任務查詢系統 | 主席樹練習題