zoukankan      html  css  js  c++  java
  • 洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002

    看来这个lct板子的确没什么问题

    好像还可以分块做

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 typedef long long LL;
      5 namespace LCT
      6 {
      7 struct Node
      8 {
      9     Node *ch[2],*fa;
     10     bool rev;
     11     LL sz;
     12     void upd()
     13     {
     14         sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1;
     15     }
     16     void pd()
     17     {
     18         if(rev)
     19         {
     20             swap(ch[0],ch[1]);
     21             if(ch[0])    ch[0]->rev^=1;
     22             if(ch[1])    ch[1]->rev^=1;
     23             rev=0;
     24         }
     25     }
     26 }nodes[300100];
     27 LL mem;
     28 Node *getnode()
     29 {
     30     return nodes+(mem++);
     31 }
     32 bool isroot(Node *x)
     33 {
     34     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
     35 }
     36 bool gson(Node *o)    {return o==o->fa->ch[1];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲
     37 void rotate(Node *o,bool d)
     38 //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d)
     39 {
     40     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会
     41     o->ch[!d]=k->ch[d];k->ch[d]=o;
     42     o->upd();k->upd();
     43     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
     44 }
     45 Node *st[300100];LL top;
     46 void solvetag(Node *o)
     47 {
     48     while(!isroot(o))    st[++top]=o,o=o->fa;
     49     st[++top]=o;
     50     while(top)    st[top--]->pd();
     51 }
     52 void splay(Node *o)
     53 {
     54     solvetag(o);
     55     Node *fa,*fafa;bool d1,d2;
     56     while(!isroot(o))
     57     {
     58         fa=o->fa;d1=(o==fa->ch[0]);
     59         if(isroot(fa))    rotate(fa,d1);
     60         else
     61         {
     62             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保证fa不是root之后才能获取这两个值,曾错过
     63             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
     64             else    rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
     65         }
     66     }
     67 }
     68 void access(Node *o)
     69 {
     70     for(Node *lst=NULL;o;lst=o,o=o->fa)
     71     {
     72         splay(o);//此处不pushdown是由于splay中保证进行过了
     73         o->ch[1]=lst;o->upd();//注意upd
     74     }
     75 }
     76 Node *gtop(Node *o)
     77 {
     78     access(o);splay(o);
     79     for(;o->ch[0];o=o->ch[0],o->pd());//此处不在开始前pushdown(o)是由于splay中保证进行过了
     80     splay(o);return o;//听说这里不splay一下也很难卡掉
     81 }
     82 void mtop(Node *o)    {access(o);splay(o);o->rev^=1;}
     83 void link(Node *x,Node *y)
     84 {
     85     if(gtop(x)==gtop(y))    return;
     86     mtop(y);y->fa=x;
     87 }
     88 void cut(Node *x,Node *y)
     89 {
     90     mtop(x);access(y);splay(y);
     91     if(y->ch[0]!=x||x->ch[1])    return;//如果x、y之间直接有边,那么上面一行的操作之后应当是x与y在单独一棵splay中,那么一定保证y左子节点是x且x没有右子节点
     92     x->fa=y->ch[0]=NULL;//注意,改的是x的父亲和y的子节点(虽然x的确是树的根,但是此时在splay上是y的子节点,不能搞混)
     93     y->upd();//注意
     94 }
     95 LL query(Node *x,Node *y)
     96 {
     97     mtop(x);access(y);splay(y);
     98     //if(gtop(y)!=x)    return 0;//此题保证x与y连通,不需要
     99     return y->sz;
    100 }
    101 }
    102 LCT::Node *nd[300100];
    103 LL n,m;char tmp[20];LL a[300100];
    104 int main()
    105 {
    106     LL i,x,y,idx;
    107     scanf("%lld",&n);
    108     for(i=0;i<=n;i++)
    109     {
    110         nd[i]=LCT::getnode();
    111         nd[i]->sz=1;
    112     }
    113     for(i=0;i<n;i++)
    114     {
    115         scanf("%lld",&a[i]);
    116         LCT::link(nd[i],nd[min(i+a[i],n)]);
    117     }
    118     scanf("%lld",&m);
    119     for(i=1;i<=m;i++)
    120     {
    121         scanf("%lld%lld",&idx,&x);
    122         if(idx==1)
    123         {
    124             printf("%lld
    ",LCT::query(nd[x],nd[n])-1);
    125         }
    126         else
    127         {
    128             scanf("%lld",&y);
    129             LCT::cut(nd[x],nd[min(x+a[x],n)]);
    130             a[x]=y;
    131             LCT::link(nd[x],nd[min(x+a[x],n)]);
    132         }
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    .NET平台系列18 .NET5的超强优势
    .NET平台系列17 .NET5中的ARM64性能
    .NET平台系列19 新世界中的.NET大统一平台架构解析
    .NET平台系列16 .NET5/Asp.Net Core 在全球Web框架权威性能测试 Web Framework Benchmarks 中的吊炸天表现
    .NET平台系列15 .NET5的吊炸天性能改进
    .NET平台系列14 .NET5中的新增功能
    从零开始学Typescript-类型注解
    从零开始学Typescript-第一个TS程序
    从零开始学Typescript-安装Typescript
    从零开始学VUE-创建VUE应用
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8885877.html
Copyright © 2011-2022 走看看