zoukankan      html  css  js  c++  java
  • BZOJ 2333: [SCOI2011]棘手的操作 可并堆 左偏树 set

    https://www.lydsy.com/JudgeOnline/problem.php?id=2333

    需要两个结构分别维护每个连通块的最大值和所有连通块最大值中的最大值,可以用两个可并堆实现,也可以用一个可并堆一个平衡树实现,我看的题解用了内置红黑树的set,更加方便,所以我也用了set。

    set的用法:https://blog.csdn.net/yas12345678/article/details/52601454 需要注意的是set的find和erase之类的操作返回输入的都是指针,在最后找最大值时,返回的是,也是指针实现的。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<set>
     7 using namespace std;
     8 const int maxn=300010;
     9 multiset<int>s;
    10 int n,q;
    11 int fa[maxn]={},rt[maxn]={},ch[maxn][2]={},cnt[maxn]={},add[maxn]={},val[maxn]={},zong=0;
    12 char op[4]={};
    13 inline void downdata(int x){
    14     if(ch[x][0]){val[ch[x][0]]+=add[x];add[ch[x][0]]+=add[x];}
    15     if(ch[x][1]){val[ch[x][1]]+=add[x];add[ch[x][1]]+=add[x];}
    16     add[x]=0;
    17 }
    18 void updata(int x){//这里的updata是把上面的所有标记传递下来
    19     if(fa[x])updata(fa[x]);
    20     downdata(x);
    21 }
    22 int merge(int x,int y){
    23     if(!y)return x;
    24     if(!x) return y;
    25     downdata(x);downdata(y);
    26     if(val[x]<val[y])swap(x,y);
    27     ch[x][1]=merge(ch[x][1],y);fa[ch[x][1]]=x;
    28     if(ch[x][0]<ch[x][1])swap(ch[x][0],ch[x][1]);
    29     cnt[x]=cnt[ch[x][1]]+1;
    30     return x;
    31 }
    32 int Find(int x){
    33     return fa[x]?Find(fa[x]):x;
    34 }
    35 inline int cle(int x){//把x与他的父亲儿子断绝关系,return堆顶
    36     int t=merge(ch[x][0],ch[x][1]),y=fa[x];
    37     fa[x]=ch[x][0]=ch[x][1]=0;
    38     if(x==ch[y][0])ch[y][0]=t;
    39     if(x==ch[y][1])ch[y][1]=t;
    40     fa[t]=y;
    41     return Find(t);
    42 }
    43 inline void del(int x){
    44     s.erase(s.find(x));
    45 }
    46 int main(){
    47     scanf("%d",&n);
    48     for(int i=1;i<=n;i++){scanf("%d",&val[i]);s.insert(val[i]);}
    49     scanf("%d",&q);int x,y,xx,yy;
    50     for(int i=1;i<=q;i++){
    51         scanf("%s",op);
    52         if(op[0]=='A'){
    53             scanf("%d",&x);
    54             if(op[1]=='1'){
    55                 scanf("%d",&y);
    56                 updata(x);del(val[Find(x)]);val[x]+=y;
    57                 s.insert(val[merge(x,cle(x))]);
    58             }
    59             else if(op[1]=='2'){
    60                 scanf("%d",&y);
    61                 xx=Find(x);del(val[xx]);add[xx]+=y;val[xx]+=y;
    62                 s.insert(val[xx]);
    63             }
    64             else zong+=x;
    65         }
    66         else if(op[0]=='F'){
    67             if(op[1]=='1'){
    68                 scanf("%d",&x);updata(x);printf("%d
    ",val[x]+zong);
    69             }
    70             else if(op[1]=='2'){
    71                 scanf("%d",&x);
    72                 printf("%d
    ",val[Find(x)]+zong);
    73             }
    74             else{
    75                 printf("%d
    ",*(--s.end())+zong);
    76             }
    77         }else{
    78             scanf("%d%d",&x,&y);
    79             yy=Find(y);xx=Find(x);
    80             if(xx!=yy){
    81                 if(merge(xx,yy)==xx)del(val[yy]);
    82                 else del(val[xx]);
    83             }
    84         }
    85     }
    86     return 0;
    87 }
    可并堆+set

    这道题的另一个写法是离线+线段树,将所有需要并到一起的点离线处理编号在线段树上放到一起,也很清晰。 

    这里将点排序的方法大概是桶排序?

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<set>
      7 using namespace std;
      8 #define lc x*2
      9 #define rc x*2+1
     10 const int maxn=300010;
     11 int n,q;
     12 char ch[4]={};
     13 int val[maxn]={},rig[maxn]={},b[maxn]={},op[maxn][3]={};
     14 int e[maxn][2]={},fa[maxn]={},cnt=0,sum[maxn]={},tail=0;
     15 int a[maxn]={};
     16 int xl[maxn*4]={},xr[maxn*4]={};
     17 int mx[maxn*4]={},ad[maxn*4]={};
     18 int id1,id2,v,zong=0;
     19 int getfa(int x){
     20     return x==fa[x]?x:getfa(fa[x]);
     21 }
     22 inline void downdata(int x,int l,int r){
     23     if(l!=r){
     24         mx[lc]+=ad[x];mx[rc]+=ad[x];
     25         ad[lc]+=ad[x];ad[rc]+=ad[x];
     26     }
     27     ad[x]=0;
     28 }
     29 inline void updata(int x,int l,int r){
     30     if(l!=r)mx[x]=max(mx[lc],mx[rc]);
     31 }
     32 void build(int x,int l,int r){
     33     if(l==r){mx[x]=a[l];return;}
     34     downdata(x,l,r);
     35     int mid=(l+r)/2;
     36     build(lc,l,mid);
     37     build(rc,mid+1,r);
     38     updata(x,l,r);
     39 }
     40 void addit(int x,int l,int r){
     41     if(id1<=l&&r<=id2){ad[x]+=v;mx[x]+=v;return;}
     42     int mid=(l+r)/2;
     43     downdata(x,l,r);
     44     if(id1<=mid)addit(lc,l,mid);
     45     if(id2>mid)addit(rc,mid+1,r);
     46     updata(x,l,r);
     47 }
     48 int getmx(int x,int l,int r){
     49     if(id1<=l&&r<=id2){return mx[x];}
     50     int mid=(l+r)/2,mm=maxn*(-2000);
     51     downdata(x,l,r);
     52     if(id1<=mid)mm=max(getmx(lc,l,mid),mm);
     53     if(id2>mid)mm=max(getmx(rc,mid+1,r),mm);
     54     updata(x,l,r);
     55     return mm;
     56 }
     57 int main(){
     58     scanf("%d",&n);
     59     for(int i=1;i<=n;i++){scanf("%d",&val[i]);fa[i]=i;sum[i]=1;}
     60     scanf("%d",&q);
     61     int x,y,xx,yy;
     62     for(int i=1;i<=q;i++){
     63         scanf("%s",ch);
     64         if(ch[0]=='U'){
     65             op[i][0]=0;
     66             scanf("%d%d",&x,&y);op[i][1]=x;op[i][2]=y;
     67             xx=getfa(x);yy=getfa(y);
     68             if(xx==yy)continue;
     69             if(xx>yy)swap(xx,yy);
     70             fa[yy]=xx;e[++cnt][0]=xx;e[cnt][1]=yy;sum[xx]+=sum[yy];
     71         }
     72         else if(ch[0]=='A'){
     73             scanf("%d",&op[i][1]);
     74             if(ch[1]=='1'){op[i][0]=1;scanf("%d",&op[i][2]);}
     75             else if(ch[1]=='2'){op[i][0]=2;scanf("%d",&op[i][2]);}
     76             else op[i][0]=3;
     77         }
     78         else{
     79             if(ch[1]=='1'){op[i][0]=4;scanf("%d",&op[i][1]);}
     80             else if(ch[1]=='2'){op[i][0]=5;scanf("%d",&op[i][1]);}
     81             else op[i][0]=6;
     82         }
     83     }
     84     for(int i=1;i<=n;i++){
     85         if(fa[i]==i){
     86             b[i]=tail+1;tail+=sum[i];rig[i]=tail;
     87             a[b[i]]=val[i];
     88         }
     89     }
     90     for(int i=cnt;i>0;i--){
     91         b[e[i][1]]=rig[e[i][0]]-sum[e[i][1]]+1;
     92         rig[e[i][1]]=rig[e[i][0]];rig[e[i][0]]=b[e[i][1]]-1;
     93         a[b[e[i][1]]]=val[e[i][1]];
     94     }
     95     for(int i=1;i<=n;i++){fa[i]=i;xl[i]=xr[i]=i;/*cout<<i<<b[i]<<endl;*/}
     96     build(1,1,n);
     97     for(int i=1;i<=q;i++){
     98         if(op[i][0]==0){
     99             xx=getfa(b[op[i][1]]);yy=getfa(b[op[i][2]]);
    100             if(xx>yy)swap(xx,yy);
    101             xr[xx]=xr[yy];fa[yy]=xx;
    102         }
    103         else if(op[i][0]==1){id1=b[op[i][1]];id2=id1;v=op[i][2];addit(1,1,n);}
    104         else if(op[i][0]==2){
    105             xx=getfa(b[op[i][1]]);
    106             id1=xl[xx];id2=xr[xx];v=op[i][2];
    107             addit(1,1,n);
    108         }
    109         else if(op[i][0]==3){
    110             zong+=op[i][1];
    111         }
    112         else if(op[i][0]==4){
    113             id1=b[op[i][1]];id2=id1;
    114             printf("%d
    ",getmx(1,1,n)+zong);
    115         }
    116         else if(op[i][0]==5){
    117             xx=getfa(b[op[i][1]]);id1=xl[xx];id2=xr[xx];
    118             printf("%d
    ",getmx(1,1,n)+zong);
    119         }
    120         else{
    121             printf("%d
    ",mx[1]+zong);
    122         }//id1=1;id2=2;
    123         //cout<<getmx(1,1,n)<<' '<<1<<endl;
    124     }
    125     return 0;
    126 }
    离线+线段树

  • 相关阅读:
    随笔记:目录已在,但是导入时报ModuleNotFoundError: No module named 'config'
    随笔记:fixture的使用
    python随笔:os.path中的realpathdirnamejoin的学习
    01-移动营销设计-认识H5与广告
    Java web开发 01 入门知识
    Java 12网络编程
    java09 面向对象,封装,继承,多态
    java08 数组与集合
    java07 数组 与 开发工具IntelliJ IDEA 安装 汉化
    java06 顺序结构 选择判断结构 与循环语句
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8690109.html
Copyright © 2011-2022 走看看