[USACO17DEC]Milk Measurement(平衡树)
题意
最初,农夫约翰的每头奶牛每天生产G加仑的牛奶 (1≤G≤109)(1≤G≤10^9)(1≤G≤109) 。由于随着时间的推移,奶牛的产奶量可能会发生变化,农夫约翰决定定期对奶牛的产奶量进行测量,并将其记录在日志中。
他的日志中的记录如下:
35 1234 -2
14 2345 +3
第一个条目表明:在第35天,1234号奶牛的产奶量比上次测量时降低了2加仑。
第二个条目表明:在第14天,2345号奶牛的产奶量比上次测量时增加了3加仑。
农夫约翰只有在任何一天内做最多一次测量的时间(即每天最多做一次测量,但可能不做)。不幸的是,约翰有点杂乱无章,他不一定按照时间顺序记下测量结果。为了保持奶牛的产奶动力,农夫约翰自豪地在谷仓的墙上展示了目前产奶量最高的奶牛的照片(如果有若干头奶牛的产奶量最高,他就会展示所有的图片)。
请求出约翰需要调整所展示的照片的次数。
请注意,农夫约翰有一大群奶牛。所以尽管日志中记录了一些奶牛改变了产奶量,但仍然还有很多奶牛的产奶量保持在G加仑。
题解
每一个时间只有一个奶牛产奶量会变化。
我们算出变化前的产奶量的排名,和变化后的产奶量排名。
如果发现是从第一变到不是第一,或从不是第一到第一,那照片一定发生变化。
如果变化后,和变化前都是第一。照片可能变也可能不会变,分四种情况讨论:
1,、可能一开始有很多奶牛并列第一,然后其中的一个奶牛独占了第一。这时照片会变。
2、一开始一个奶牛是第一,然后产奶量增加还是第一,显然不变。
3、也有可能开始一个奶牛第一然后,产奶量下降,变得和第二一样,这时会变。
4、一开始一个奶牛是第一,然后产奶量下降但比第二高还是第一,显然不变。
所以我们找出产奶量为变化之前的奶牛的数量,和产奶量为变化之后的奶牛的数量,判断相不相等即可。
这些东西都可以用平衡树维护。(权值线段树,主席树什么的当然也可以)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 #include<map> 7 using namespace std; 8 const int N=500010; 9 map<int,int>ma; 10 int n,g,mx,num; 11 int a[N],b[N],ans[N]; 12 int cnt[N],size[N],ch[N][2],fa[N],v[N]; 13 int root,tot; 14 struct hhh{ 15 int t,id,w; 16 }c[N]; 17 bool cmp(hhh a,hhh b){ 18 return a.t<b.t; 19 } 20 void update(int x){ 21 size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x]; 22 } 23 int son(int x){ 24 return x==ch[fa[x]][1]; 25 } 26 void rotate(int x){ 27 int y=fa[x],z=fa[y],a=son(x),b=son(y),c=ch[x][!a]; 28 if(z)ch[z][b]=x; 29 else root=x; 30 fa[x]=z; 31 if(c)fa[c]=y; 32 ch[x][!a]=y; 33 ch[y][a]=c; 34 fa[y]=x; 35 update(y); 36 update(x); 37 } 38 void splay(int x,int f){ 39 while(fa[x]!=f){ 40 int y=fa[x]; 41 int z=fa[y]; 42 if(z==f)rotate(x); 43 else{ 44 if(son(y)==son(x))rotate(y); 45 else rotate(x); 46 rotate(x); 47 } 48 } 49 if(f==0)root=x; 50 } 51 void ins(int x){ 52 int p=root; 53 int f=0; 54 while(p&&v[p]!=x){ 55 f=p; 56 size[p]++; 57 p=ch[p][v[p]<x]; 58 } 59 if(p){ 60 size[p]++; 61 cnt[p]++; 62 } 63 else{ 64 p=++tot; 65 if(f)ch[f][v[f]<x]=p; 66 size[p]=cnt[p]=1; 67 v[p]=x; 68 fa[p]=f; 69 } 70 splay(p,0); 71 } 72 int getmn(int rt){ 73 int p=rt,ans=-1; 74 while(p){ 75 ans=p; 76 p=ch[p][0]; 77 } 78 return ans; 79 } 80 81 void del(int rt,int x){ 82 if(v[rt]==x){ 83 if(cnt[rt]>1)cnt[rt]--,size[rt]--; 84 else{ 85 splay(rt,0); 86 int p=getmn(ch[rt][1]); 87 if(p!=-1){ 88 splay(p,rt); 89 root=p; 90 fa[p]=0; 91 ch[p][0]=ch[rt][0]; 92 fa[ch[rt][0]]=p; 93 update(p); 94 } 95 else { 96 root=ch[rt][0]; 97 fa[root]=0; 98 } 99 } 100 return; 101 } 102 if(x<v[rt])del(ch[rt][0],x),update(rt); 103 else del(ch[rt][1],x),update(rt); 104 } 105 int rank(int rt,int k){ 106 if(v[rt]==k){ 107 splay(rt,0); 108 return size[ch[rt][1]]+1; 109 } 110 if(k<v[rt])return rank(ch[rt][0],k); 111 else return rank(ch[rt][1],k); 112 } 113 int getsame(int rt,int x){ 114 if(v[rt]==x){ 115 splay(rt,0); 116 return cnt[rt]; 117 } 118 if(x<v[rt])return rank(ch[rt][0],x); 119 else return rank(ch[rt][1],x); 120 } 121 int main(){ 122 scanf("%d%d",&n,&g); 123 for(int i=1;i<=n;i++){ 124 scanf("%d%d",&c[i].t,&c[i].id); 125 char ch; 126 cin>>ch; 127 scanf("%d",&c[i].w); 128 if(ch=='-')c[i].w=-c[i].w; 129 b[i]=c[i].id; 130 } 131 sort(b+1,b+1+n); 132 int cnt=unique(b+1,b+1+n)-b-1; 133 for(int i=1;i<=n;i++){ 134 c[i].id=lower_bound(b+1,b+1+cnt,c[i].id)-b; 135 } 136 sort(c+1,c+1+n,cmp); 137 for(int i=1;i<=cnt+1;i++){ 138 a[i]=g; 139 ins(g); 140 } 141 ma[g]=cnt+1; 142 for(int i=1;i<=n;i++){ 143 // cout<<";asjhfljashfjashdfasdf"<<endl; 144 if(c[i].w==0)continue; 145 int k=rank(root,a[c[i].id]); 146 int num1=getsame(root,a[c[i].id]); 147 // cout<<k<<" "<<num1<<endl<<"aaa"<<endl; 148 del(root,a[c[i].id]); 149 a[c[i].id]+=c[i].w; 150 ins(a[c[i].id]); 151 int kk=rank(root,a[c[i].id]); 152 int num2=getsame(root,a[c[i].id]); 153 if((kk==1&&k!=1)||(k==1&&kk!=1)||(num1!=num2&&kk==1&&k==1)){ 154 ans[++num]=c[i].t; 155 } 156 } 157 printf("%d\n",num); 158 // for(int i=1;i<=num;i++){ 159 // printf("%d\n",ans[i]); 160 // } 161 return 0; 162 } 163 /* 164 4 10 165 7 3 +3 166 4 2 -1 167 9 3 -1 168 1 1 +2 169 */