主席树 别人眼中的模板,我眼中的难题。

这道题如果是在比赛中出现的话,可能会输在了英语上。

题意:给你m,n;m是操作个数,n是询问个数(询问的数也是n的排列,意思是 如果是3,那么接下来的询问,可能是3 2 1 ,1 2 3,2 3 1,这样 )

在这种情况下,会想到差分的思想,在本题中,我用邻接表,把区间左右端点存进去。

然后再从左往右遍历1~n秒的时候有多少个任务,后面一个可以在前面一个的基础上继续操作。

用root【1~n】去表示每一个点的数,也就是说,每一个点建一颗树去表示。

建完之后,询问,就很简单了,类似于求第k大的数是多少,这道题求的是,前k个数的总和

这道题有两个细节:1.如果k大于总和,就直接输出这棵树的最大值;

                                 2.

 

                                  这个不能直接return tree[root].sum  因为在这个点可能不止有k个数,所以只能return k 个。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
 5 const int maxn=1e5+10;
 6 typedef long long ll;
 7 int b[maxn];
 8 int root[maxn];
 9 struct node
10 {
11     int base,val,flag;
12     int next;
13 }G[maxn*2]; int num;
14 int head[maxn*2];
15 struct Node
16 {
17     int ln,rn,sum,Size;
18 }tree[maxn*40];  //大小还没确定好;
19 int tot;
20 void add(int base,int val,int flag)
21 {
22     G[++num].val=val;G[num].flag=flag;G[num].next=head[base];head[base]=num;
23 }
24 void init()
25 {
26     memset(head,-1,sizeof(head));
27     num=0;
28 }
29 void pushup(int root)
30 {
31     int left=tree[root].ln,right=tree[root].rn;
32     tree[root].sum=tree[left].sum+tree[right].sum;
33     tree[root].Size=tree[left].Size+tree[right].Size;
34 }
35 void update(int y,int &x,int l,int r,int p,int k)
36 {
37     tree[++tot]=tree[y];
38     x=tot;
39     if(l==r){
40         tree[tot].sum+=b[l]*k;
41         tree[tot].Size+=k;
42         return;
43     }
44     int mid=l+r>>1;
45     if(p<=mid) update(tree[y].ln,tree[x].ln,l,mid,p,k);
46     else update(tree[y].rn,tree[x].rn,mid+1,r,p,k);
47     pushup(x);
48 }
49 ll query(int root,int l,int r,int k)
50 {
51     if(l==r) return 1ll*k*b[l];
52     int left=tree[root].ln,right=tree[root].rn;
53     int mid=l+r>>1;
54     if(tree[left].Size>=k) return query(left,l,mid,k);
55     else return tree[left].sum+query(right,mid+1,r,k-tree[left].Size);
56 }
57 int main()
58 {
59     int m,n;
60     scanf("%d%d",&m,&n);
61     init();
62     for(int i=1;i<=m;i++){
63         int t1,t2,t3;
64         scanf("%d%d%d",&t1,&t2,&t3);
65         add(t1,t3,1),add(t2+1,t3,-1);
66         b[i]=t3;
67     }
68     sort(b+1,b+1+m);
69     int len=unique(b+1,b+1+m)-b-1;
70     int last=0;
71     for(int i=1;i<=n;i++){
72         root[i]=last;   
73         for(int j=head[i];j!=-1;j=G[j].next){
74             G[j].val=lower_bound(b+1,b+1+len,G[j].val)-b;
75             update(last,root[i],1,len,G[j].val,G[j].flag);
76             last=root[i];
77         }
78     }
79     ll pre=1;
80     for(int i=1;i<=n;i++){
81         int x,t1,t2,t3;
82         scanf("%d%d%d%d",&x,&t1,&t2,&t3);
83         int k=1+(t1*pre+t2)%t3;
84         int tmp=root[x];
85         if(tree[tmp].Size<=k) pre=tree[tmp].sum;
86         else pre=query(tmp,1,len,k);
87         printf("%lld\n",pre);
88     }
89     return 0;
90 }

 

posted @ 2019-10-11 13:36  古比  阅读(171)  评论(0编辑  收藏  举报