zoukankan      html  css  js  c++  java
  • [USACO17DEC]Milk Measurement(平衡树)

    题意

    最初,农夫约翰的每头奶牛每天生产G加仑的牛奶 (1≤G≤109)(1≤G≤10^9)(1G109) 。由于随着时间的推移,奶牛的产奶量可能会发生变化,农夫约翰决定定期对奶牛的产奶量进行测量,并将其记录在日志中。

    他的日志中的记录如下:

    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
    ",num);
    158 //    for(int i=1;i<=num;i++){
    159 //        printf("%d
    ",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 */
  • 相关阅读:
    第二周总结
    2019春总结作业
    第二次编程总结
    第四周作业
    第十二周作业
    第十一周作业
    第十周作业
    第九周作业
    第八周作业
    第六周作业
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9529677.html
Copyright © 2011-2022 走看看