主席树 别人眼中的模板,我眼中的难题。
这道题如果是在比赛中出现的话,可能会输在了英语上。
题意:给你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 }