【主席树】BZOJ3932-[CQOI2015]任务查询系统
【题目大意】
超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
【思路】
主席树。在Si秒开始,在Ei秒结束,相当于在Si秒加一,在Ei秒减一的前缀和。
把优先级看作数值,把时间看作T树下标。将优先级离散化后,按照时间排序,记录三元组(time,p,delta),描述时间,优先级及变化量(+1或-1),对于同一个时间,如果当前时间第一次出现,在T[time-1]的基础上更新,否则在T[time]的基础上更新。注意,中间空白的时间段,T[time]=T[time-1]。
【错误点】
query返回条件,但l==r时,不可以直接返回sum,而是sum/size*k。
因为我当前的size可能大于k。
1 //时刻->下标 2 //优先级->数值 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #define lson l,m 9 #define rson m+1,r 10 using namespace std; 11 const int MAXN=100000+50; 12 typedef long long ll; 13 struct node 14 { 15 int time,p,delta; 16 17 }a[MAXN*2]; 18 bool cmp(node x,node y) 19 { 20 return (x.time<y.time); 21 } 22 int m,n,tot,d; 23 int hash[MAXN],T[MAXN],size[MAXN<<7],L[MAXN<<7],R[MAXN<<7]; 24 ll sum[MAXN<<7]; 25 26 int build(int l,int r) 27 { 28 int rt=++tot; 29 sum[rt]=size[rt]=0; 30 if (l<r) 31 { 32 int m=(l+r)>>1; 33 L[rt]=build(lson); 34 R[rt]=build(rson); 35 } 36 return rt; 37 } 38 39 int update(int pre,int l,int r,int x,int delta) 40 { 41 int rt=++tot; 42 L[rt]=L[pre],R[rt]=R[pre]; 43 sum[rt]=sum[pre]+(ll)delta*hash[x]; // sum 优先级的和:例如两个优先级为3的人物,那么sum=6,而size=2 44 size[rt]=size[pre]+delta; // size 优先级个数的和:例如两个优先级为3的人物,那么sum=6,而size=2 45 if (l!=r) 46 { 47 int m=(l+r)>>1; 48 if (x<=m) L[rt]=update(L[rt],lson,x,delta); 49 else R[rt]=update(R[rt],rson,x,delta); 50 } 51 return rt; 52 } 53 54 55 ll query(int rt,int l,int r,ll k) 56 { 57 int nowsize=size[rt]; 58 if (k>=nowsize) return (sum[rt]); 59 if (l==r) return (sum[rt]/size[rt]*k); 60 //当l==r时,当前值可能有多个,且总数大于k,所以只需返回k*当前值即可 61 int num=size[L[rt]]; 62 ll ret; 63 int m=(l+r)>>1; 64 if(num>=k) 65 ret=query(L[rt], lson, k); 66 else 67 ret=sum[L[rt]]+query(R[rt],rson, k-num); 68 return ret; 69 } 70 71 void init() 72 { 73 tot=0; 74 scanf("%d%d",&m,&n); 75 for (int i=1;i<=m;i++) 76 { 77 int s,e,p; 78 scanf("%d%d%d",&s,&e,&p); 79 a[2*i-1]=(node){s,p,1}; 80 a[2*i]=(node){e+1,p,-1}; 81 hash[i]=p; 82 } 83 sort(hash+1,hash+m+1); 84 m=m*2; 85 sort(a+1,a+m+1,cmp); 86 87 d=unique(hash+1,hash+(m>>1)+1)-(hash+1); 88 T[0]=build(1,d); 89 for (int i=1;i<=m;i++) 90 { 91 int x=lower_bound(hash+1,hash+d+1,a[i].p)-hash; 92 int t=a[i].time; 93 if (i==1 || t!=a[i-1].time) 94 { 95 if (i!=1) for (int j=a[i-1].time+1;j<t;j++) T[j]=T[j-1]; 96 T[t]=update(T[t-1],1,d,x,a[i].delta); 97 } 98 else T[t]=update(T[t],1,d,x,a[i].delta); 99 } 100 } 101 102 void solve() 103 { 104 int pre=1; 105 for (int i=0;i<n;i++) 106 { 107 ll x,a,b,c; 108 scanf("%lld%lld%lld%lld",&x,&a,&b,&c); 109 ll k=1+(ll)(a*pre+b)%c; 110 ll ans=query(T[x],1,d,k); 111 printf("%lld\n",ans); 112 pre=ans; 113 } 114 } 115 116 int main() 117 { 118 //freopen("cqoi15_query.in","r",stdin); 119 //freopen("cqoi15_query.out","w",stdout); 120 init(); 121 solve(); 122 return 0; 123 }