bzoj 2157 旅游

Posted narh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于bzoj 2157 旅游的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2157 旅游(树链剖分+线段树)

BZOJ2157: 旅游 树链剖分 线段树

BZOJ2157旅游 LCT

bzoj 2157 旅游

BZOJ_2157_旅游_树剖+线段树

bzoj2157: 旅游