zoukankan      html  css  js  c++  java
  • bzoj 2157 旅游

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2157

    明明是裸LCT板子……

    注意pshp的那个地方!原以为把0~n的mx、mn都赋好初值就能随便弄了,仔细想想要用的是val!

      而且还是既用在max里又用在min里,故不能赋初值来怎样,应当分类讨论!

    关于变成相反数的操作,原来也是打标记!而且标记的含义和线段树的一样,表示自己已经操作过、要给孩子操作。这样才能保证query的正确。

      可是自己那种dfs来当即弄成相反数的做法为什么不行???

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=2e4+5,M=4e4+5;
    int n,m,pre[M],sum[M],val[M],mx[M],mn[M],c[M][2],stack[M],top,sta[M];
    bool rev[M];
    bool isroot(int x){return c[pre[x]][0]!=x&&c[pre[x]][1]!=x;}
    void pshp(int x)
    {
      int ls=c[x][0],rs=c[x][1];
      sum[x]=val[x]+sum[ls]+sum[rs];
      mx[x]=max(mx[ls],mx[rs]);
      mn[x]=min(mn[ls],mn[rs]);
      if(x>n)mx[x]=max(val[x],mx[x]),mn[x]=min(val[x],mn[x]);
    //  mx[x]=max(val[x],max(mx[ls],mx[rs]));
    //  mn[x]=min(val[x],min(mn[ls],mn[rs]));
    }
    void reverse(int x)
    {
      if(rev[x])
        {
          rev[c[x][0]]^=1;rev[c[x][1]]^=1;
          swap(c[x][0],c[x][1]);
          rev[x]=0;
        }
    }
    void rotate(int x)
    {
      int y=pre[x],z=pre[y],d=(x==c[y][1]);
      if(!isroot(y))c[z][y==c[z][1]]=x;
      pre[x]=z;pre[y]=x;
      c[y][d]=c[x][!d];pre[c[x][!d]]=y;c[x][!d]=y;
      pshp(y);pshp(x);
    }
    void splay(int x)
    {
      stack[top=1]=x;
      for(int t=x;!isroot(t);t=pre[t])stack[++top]=pre[t];
      for(;top;top--)reverse(stack[top]);
      for(;!isroot(x);rotate(x))
        {
          int y=pre[x],z=pre[y];
          if(isroot(y))continue;
          ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y);
        }
    }
    void access(int x)
    {
      for(int t=0;x;c[x][1]=t,pshp(x),t=x,x=pre[x])splay(x);
    }
    void makeroot(int x)
    {
      access(x);splay(x);rev[x]^=1;
    }
    void query(int x,int y)
    {
      makeroot(x);access(y);splay(y);
    }
    void link(int x,int y)
    {
      makeroot(x);pre[x]=y;
    }
    void dfs(int cr)
    {
      val[cr]=-val[cr];
      if(c[cr][0])dfs(c[cr][0]);
      if(c[cr][1])dfs(c[cr][1]);
      pshp(cr);
    }
    int main()
    {
      scanf("%d",&n);int x,y,z;
      mx[0]=-1005;mn[0]=1005;//写在link前 
      for(int i=1;i<n;i++)
        {
          scanf("%d%d%d",&x,&y,&z);x++;y++;
          val[i+n]=z;
          link(i+n,x);link(i+n,y);
        }
      char ch[5];
      scanf("%d",&m);
      while(m--)
        {
          scanf("%s%d%d",ch,&x,&y);
          if(ch[0]!='C')x++,y++,query(x,y);//仅!='C'时++!!! 
          if(ch[0]=='C'){
        splay(x+n);val[x+n]=y;pshp(x+n);
          }
          else if(ch[0]=='N')dfs(x);
          else if(ch[1]=='U')printf("%d
    ",sum[y]);
          else if(ch[1]=='A')printf("%d
    ",mx[y]);
          else printf("%d
    ",mn[y]);
        }
      return 0;
    }
    会WA的做法
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=2e4+5,M=4e4+5;
    int n,m,pre[M],sum[M],val[M],mx[M],mn[M],c[M][2],stack[M],top,sta[M],tp;
    bool rev[M],tag[M];
    bool isroot(int x){return c[pre[x]][0]!=x&&c[pre[x]][1]!=x;}
    void pshp(int x)
    {
      int ls=c[x][0],rs=c[x][1];
      sum[x]=val[x]+sum[ls]+sum[rs];
      mx[x]=max(mx[ls],mx[rs]);
      mn[x]=min(mn[ls],mn[rs]);
      if(x>n)mx[x]=max(mx[x],val[x]),mn[x]=min(mn[x],val[x]);//////
    //  mx[x]=max(val[x],max(mx[ls],mx[rs]));
    //  mn[x]=min(val[x],min(mn[ls],mn[rs]));
    }
    void tg(int x)
    {
        sum[x]=-sum[x];val[x]=-val[x];tag[x]^=1;
        swap(mn[x],mx[x]);mx[x]=-mx[x];mn[x]=-mn[x];
    }
    void pshd(int x)
    {
        int ls=c[x][0],rs=c[x][1];
        if(rev[x])
        {
          rev[ls]^=1;rev[rs]^=1;
          swap(c[x][0],c[x][1]);
          rev[x]=0;
        }
        if(tag[x])
        {
            tag[x]=0;if(ls)tg(ls);if(rs)tg(rs);
        }
    }
    void rotate(int x)
    {
      int y=pre[x],z=pre[y],d=(x==c[y][1]);
      if(!isroot(y))c[z][y==c[z][1]]=x;
      pre[x]=z;pre[y]=x;
      c[y][d]=c[x][!d];pre[c[x][!d]]=y;c[x][!d]=y;
      pshp(y);pshp(x);
    }
    void splay(int x)
    {
      stack[top=1]=x;
      for(int t=x;!isroot(t);t=pre[t])stack[++top]=pre[t];
      for(;top;top--)pshd(stack[top]);    //倒序,标记才能全清除 
      for(;!isroot(x);rotate(x))
        {
          int y=pre[x],z=pre[y];
          if(isroot(y))continue;
          ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y);
        }
    }
    void access(int x)
    {
      for(int t=0;x;splay(x),c[x][1]=t,pshp(x),t=x,x=pre[x]);
    }
    void makeroot(int x)
    {
      access(x);splay(x);rev[x]^=1;
    }
    void query(int x,int y)
    {
      makeroot(x);access(y);splay(y);
    }
    void link(int x,int y)
    {
      makeroot(x);pre[x]=y;
    }
    void chg(int x,int y)
    {
        splay(x);val[x]=y;pshp(x);//splay即可,不用makeroot 
    }
    int main()
    {
      scanf("%d",&n);int x,y,z;
      mx[0]=-1005;mn[0]=1005;
    //  for(int i=0;i<=n;i++)mx[i]=-1005,mn[i]=1005;//
      for(int i=1;i<n;i++)
        {
          scanf("%d%d%d",&x,&y,&z);x++;y++;
          val[i+n]=z;
          link(i+n,x);link(i+n,y);
        }
      char ch[5];
      scanf("%d",&m);
      while(m--)
        {
          scanf("%s%d%d",ch,&x,&y);
          if(ch[0]!='C')x++,y++,query(x,y);//仅!='C'时++!!! 
          if(ch[0]=='C')chg(x+n,y);
          else if(ch[0]=='N')tg(y);
          else if(ch[1]=='U')printf("%d
    ",sum[y]);
          else if(ch[1]=='A')printf("%d
    ",mx[y]);
          else printf("%d
    ",mn[y]);
        }
      return 0;
    }
  • 相关阅读:
    模拟赛QAQ
    复习计划
    luogu P1080 国王游戏
    [NOIP2012T3]开车旅行
    luogu P1967 货车运输
    同余方程组的扩展欧几里得解法
    luogu P1476 休息中的小呆
    GRYZY #13. 拼不出的数
    GRYZY- #10. 财富
    GRYZY #8. 公交车
  • 原文地址:https://www.cnblogs.com/Narh/p/9241785.html
Copyright © 2011-2022 走看看