【主席树】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 } 

 

posted @ 2016-08-14 09:37  iiyiyi  阅读(694)  评论(0编辑  收藏  举报