• bzoj2333[SCOI2011]棘手的操作 洛谷P3273 [SCOI2011]棘手的操作


    2333?

    先记一下吧,这题现在全部都是照着题解做的,因为怎么改都改不出来,只好对着题解改,以后还要再做过

    以后再也不用指针了!太恶心了!空指针可不止直接特判那么简单啊,竟然还要因为空指针写奇怪的分类讨论!

    没错,就是那个诡异的55和63行。由于要返回删除x后x所在树的新根,要分类讨论:如果x是根且其两个子节点合并后为空,那么去掉x后新树树根为空;如果x是根且其两个子节点合并后不为空,那么去掉x后新树树根为两个子节点合并后的;如果x不是根,那么去掉x后新树树根为原来的find(x)。

    另外,打了注释号的(不管是空注释还是被注释掉的语句)都表示此处出过错

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<set>
      4 using namespace std;
      5 multiset<int> sx;
      6 void erase(int x)
      7 {
      8     //if(sx.find(x)!=sx.end())    
      9     sx.erase(sx.find(x));
     10 }
     11 struct Node
     12 {
     13     int data;int addv;
     14     Node *ch[2],*fa;
     15     void pd()
     16     {
     17         if(addv)
     18         {
     19             if(ch[0])    ch[0]->addv+=addv,ch[0]->data+=addv;
     20             if(ch[1])    ch[1]->addv+=addv,ch[1]->data+=addv;
     21             addv=0;//
     22         }
     23     }
     24 }nodes[300010];
     25 Node* find(Node* x)//
     26 {
     27     if(x==NULL)    return x;//
     28     while(x->fa)    x=x->fa;
     29     return x;
     30 }
     31 Node* merge(Node* a,Node* b)
     32 {
     33     if(!a)    return b;
     34     if(!b)    return a;
     35     //a->pd();b->pd();
     36     if(a->data < b->data)    swap(a,b);
     37     a->pd();
     38     a->ch[1]=merge(a->ch[1],b);
     39     if(a->ch[1])/**/    a->ch[1]->fa=a;
     40     swap(a->ch[0],a->ch[1]);
     41     return a;
     42 }
     43 Node *q[300010];int q_num;
     44 void solvetag(Node *x)//
     45 {
     46     while(x)q[++q_num]=x,x=x->fa;
     47     //while(x->fa)q[++q_num]=x,x=x->fa;
     48     while(q_num)q[q_num--]->pd();
     49 }
     50 Node* del(Node *x)//删除x,将x较大的儿子提上来,并返回它所在集合的新根节点
     51 {
     52     //if(x==NULL)    return x;//''
     53     solvetag(x);
     54     Node *t=merge(x->ch[0],x->ch[1]),*f=x->fa,*rt;
     55     rt=find(x);if(rt==x)    rt=NULL;//
     56     x->ch[0]=x->ch[1]=x->fa=NULL;
     57     if(f)//
     58     {
     59         if(x==f->ch[0])    f->ch[0]=t;
     60         else    f->ch[1]=t;
     61     }
     62     if(t)/**/    t->fa=f;
     63     if(t)    rt=find(t);//
     64     return rt;
     65 }
     66 void add(Node *x,int val)
     67 {
     68     //if(x==NULL)    return;
     69     solvetag(x);
     70     erase(find(x)->data);
     71     //find(x)->data+=val;
     72     x->data+=val;Node *t=del(x);
     73     sx.insert(merge(x,t)->data);//puts("t1");
     74 }
     75 void hadd(Node *x,int val)
     76 {
     77     //if(x==NULL)    return;//'
     78     Node *p=find(x);
     79     erase(p->data);
     80     p->addv+=val;p->data+=val;
     81     sx.insert(p->data);
     82 }
     83 int n,m,addx,Q;
     84 char tmp[102];
     85 int main()
     86 {
     87     int i,t,x,y,v;Node *fx,*fy;
     88     scanf("%d",&n);
     89     for(i=1;i<=n;i++)
     90     {
     91         scanf("%d",&t);
     92         nodes[i].data=t;
     93         //nodes[i].upd();
     94         sx.insert(t);
     95     }
     96     scanf("%d",&Q);
     97     //int axx=0;
     98     while(Q--)
     99     {
    100         scanf("%s",tmp);
    101         if(tmp[0]=='U')
    102         {
    103             scanf("%d%d",&x,&y);
    104             fx=find(nodes+x);fy=find(nodes+y);
    105             if(fx==fy)    continue;
    106             //solvetag(nodes+x);solvetag(nodes+y);
    107             if(merge(fx,fy)==fx)    erase(fy->data);
    108             else    erase(fx->data);
    109         }
    110         else if(tmp[0]=='A')
    111         {
    112             if(tmp[1]=='1')
    113             {
    114                 scanf("%d%d",&x,&v);
    115                 add(nodes+x,v);
    116 
    117             }
    118             else if(tmp[1]=='2')
    119             {
    120                 scanf("%d%d",&x,&v);
    121                 hadd(nodes+x,v);
    122             }
    123             else if(tmp[1]=='3')
    124             {
    125                 scanf("%d",&v);
    126                 addx+=v;
    127             }
    128         }
    129         else if(tmp[0]=='F')
    130         {
    131             //axx++;
    132             //if(axx==54)    printf("    %c ",tmp[1]);
    133             if(tmp[1]=='1')
    134             {
    135                 scanf("%d",&x);
    136                 solvetag(nodes+x);
    137                 printf("%d
    ",nodes[x].data+addx);
    138             }
    139             else if(tmp[1]=='2')
    140             {
    141                 scanf("%d",&x);
    142                 //solvetag(nodes+x);
    143                 printf("%d
    ",find(nodes+x)->data+addx);
    144             }
    145             else if(tmp[1]=='3')
    146             {
    147                 printf("%d
    ",*(--sx.end())+addx);
    148             }
    149 
    150 
    151         }
    152     }
    153     return 0;
    154 }

    另外:本来是想不到去写斜堆的,因为斜堆并不保证任何意义上的平衡,如果用这个在节点上维护附加信息,那么标记传递还有找根什么的复杂度应该是假的。然而实际应用发现...并没有问题?仍然不会分析

    另外:把堆合并改成非旋treap里面的样子,也可以过,而且用时几乎完全一样(只差几ms)(然而去掉swap两个子节点就不能了,或者将非旋treap合并里面一些对正确性无关紧要的东西乱改一下也不行,这次跟洛谷上某道可并堆模版不一样了...),说明非旋treap里面堆合并跟一般斜堆合并写法本质应该没有区别(只是保证中序遍历不变)。然而并不会分析?

    另外:虽然不交换是错的,但是随机怎么摆却是对的!实际效果是只比斜堆慢了一点点。而且,即使斜堆真的会被卡随机堆也不可能被卡...应该吧

    就比如这样

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<set>
      4 using namespace std;
      5 multiset<int> sx;
      6 inline int rd()
      7 {
      8     static int x=471;
      9     return x=(48271LL*x+1)%2147483647;
     10 }
     11 void erase(int x)
     12 {
     13     //if(sx.find(x)!=sx.end())    
     14     sx.erase(sx.find(x));
     15 }
     16 struct Node
     17 {
     18     int data;int addv;
     19     Node *ch[2],*fa;
     20     void pd()
     21     {
     22         if(addv)
     23         {
     24             if(ch[0])    ch[0]->addv+=addv,ch[0]->data+=addv;
     25             if(ch[1])    ch[1]->addv+=addv,ch[1]->data+=addv;
     26             addv=0;//
     27         }
     28     }
     29 }nodes[300010];
     30 Node* find(Node* x)//
     31 {
     32     if(x==NULL)    return x;//
     33     while(x->fa)    x=x->fa;
     34     return x;
     35 }
     36 Node* merge(Node* a,Node* b)
     37 {
     38     if(!a)    return b;
     39     if(!b)    return a;
     40     //a->pd();b->pd();
     41     if(a->data < b->data)    swap(a,b);
     42     a->pd();
     43     if(rd()%2)
     44     {
     45         a->ch[0]=merge(a->ch[0],b);
     46         if(a->ch[0])    a->ch[0]->fa=a;
     47     }
     48     else
     49     {
     50         a->ch[1]=merge(a->ch[1],b);
     51         if(a->ch[1])    a->ch[1]->fa=a;
     52     }
     53     return a;
     54         
     55 }
     56 Node *q[300010];int q_num;
     57 void solvetag(Node *x)//
     58 {
     59     while(x)q[++q_num]=x,x=x->fa;
     60     //while(x->fa)q[++q_num]=x,x=x->fa;
     61     while(q_num)q[q_num--]->pd();
     62 }
     63 Node* del(Node *x)//删除x,将x较大的儿子提上来,并返回它所在集合的新根节点
     64 {
     65     //if(x==NULL)    return x;//''
     66     solvetag(x);
     67     Node *t=merge(x->ch[0],x->ch[1]),*f=x->fa,*rt;
     68     rt=find(x);if(rt==x)    rt=NULL;//
     69     x->ch[0]=x->ch[1]=x->fa=NULL;
     70     if(f)//
     71     {
     72         if(x==f->ch[0])    f->ch[0]=t;
     73         else    f->ch[1]=t;
     74     }
     75     if(t)/**/    t->fa=f;
     76     if(t)    rt=find(t);//
     77     return rt;
     78 }
     79 void add(Node *x,int val)
     80 {
     81     //if(x==NULL)    return;
     82     solvetag(x);
     83     erase(find(x)->data);
     84     //find(x)->data+=val;
     85     x->data+=val;Node *t=del(x);
     86     sx.insert(merge(x,t)->data);//puts("t1");
     87 }
     88 void hadd(Node *x,int val)
     89 {
     90     //if(x==NULL)    return;//'
     91     Node *p=find(x);
     92     erase(p->data);
     93     p->addv+=val;p->data+=val;
     94     sx.insert(p->data);
     95 }
     96 int n,m,addx,Q;
     97 char tmp[102];
     98 int main()
     99 {
    100     int i,t,x,y,v;Node *fx,*fy;
    101     scanf("%d",&n);
    102     for(i=1;i<=n;i++)
    103     {
    104         scanf("%d",&t);
    105         nodes[i].data=t;
    106         //nodes[i].upd();
    107         sx.insert(t);
    108     }
    109     scanf("%d",&Q);
    110     //int axx=0;
    111     while(Q--)
    112     {
    113         scanf("%s",tmp);
    114         if(tmp[0]=='U')
    115         {
    116             scanf("%d%d",&x,&y);
    117             fx=find(nodes+x);fy=find(nodes+y);
    118             if(fx==fy)    continue;
    119             //solvetag(nodes+x);solvetag(nodes+y);
    120             if(merge(fx,fy)==fx)    erase(fy->data);
    121             else    erase(fx->data);
    122         }
    123         else if(tmp[0]=='A')
    124         {
    125             if(tmp[1]=='1')
    126             {
    127                 scanf("%d%d",&x,&v);
    128                 add(nodes+x,v);
    129 
    130             }
    131             else if(tmp[1]=='2')
    132             {
    133                 scanf("%d%d",&x,&v);
    134                 hadd(nodes+x,v);
    135             }
    136             else if(tmp[1]=='3')
    137             {
    138                 scanf("%d",&v);
    139                 addx+=v;
    140             }
    141         }
    142         else if(tmp[0]=='F')
    143         {
    144             //axx++;
    145             //if(axx==54)    printf("    %c ",tmp[1]);
    146             if(tmp[1]=='1')
    147             {
    148                 scanf("%d",&x);
    149                 solvetag(nodes+x);
    150                 printf("%d
    ",nodes[x].data+addx);
    151             }
    152             else if(tmp[1]=='2')
    153             {
    154                 scanf("%d",&x);
    155                 //solvetag(nodes+x);
    156                 printf("%d
    ",find(nodes+x)->data+addx);
    157             }
    158             else if(tmp[1]=='3')
    159             {
    160                 printf("%d
    ",*(--sx.end())+addx);
    161             }
    162 
    163 
    164         }
    165     }
    166     return 0;
    167 }
    View Code

    我差点忘了一件事,就是相同权值的在堆里顺序无所谓,merge两个参数先后也是无所谓的。

  • 相关阅读:
    ecshop 浏览历史样式的修改
    ECSHOP任意页面调用商品属性
    ECShop url路径 商品详情页goods 商品列表页category 修改成你想要的
    ecshop模板增加新lbi库文件注意事项
    最完美带qq昵称qq头像的qq帐号登录ecshop插件
    ECSHOP2.72 前台调用 定单号,及收货人,快递号
    ecshop后台帐号密码忘记了怎么办?
    ECSHOP首页成功实现订单上下滚动
    ECSHOP 注册就送红包
    ECSHOP隐藏帮助中心文章页的评论功能方法
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8495457.html
Copyright © 2020-2023  润新知