[LCT || splay维护括号序列] BZOJ 4573 [Zjoi2016]大森林

题解爸爸戳这里

splay维护括号序实在不敢尝试
建虚点LCT 还是很资瓷的哇 正如dls所说的 小清新数据结构
注意的是求两点距离 不能直接拉出那条链 而是要求LCA
然后我发现我不会求LCA了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=400005;

struct node{
  node *ch[2],*f;
  int v,s; bool rev;
  bool isr() { return !f || (f->ch[0]!=this && f->ch[1]!=this); }
  bool dir() { return f->ch[1]==this; }
  void setc(node *x,int d) { ch[d]=x; if (x) x->f=this; }
  void push(){
    if (rev) { swap(ch[0],ch[1]); if(ch[0])ch[0]->rev^=1; if(ch[1])ch[1]->rev^=1; rev=0; }
  }
  void upd(){
    s=v; if(ch[0]) s+=ch[0]->s; if (ch[1]) s+=ch[1]->s;
  }
}pool[N];
inline void rot(node *x){
  bool d=x->dir(); node *p=x->f;
  if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;
  p->setc(x->ch[d^1],d); x->setc(p,d^1); p->upd();
}
stack<node*> sta;
inline void splay(node *x){
  node *q=x; while (!q->isr()) sta.push(q),q=q->f; sta.push(q);
  while (!sta.empty()) sta.top()->push(),sta.pop();
  while (!x->isr())
    if (x->f->isr()) rot(x);
    else if (x->dir()==x->f->dir()) rot(x->f),rot(x);
    else rot(x),rot(x);
  x->upd();
}
inline node *expose(node *x){
  node *p;
  for (node *q=NULL;x;q=x,x=x->f)
    p=x,splay(x),x->ch[1]=q,x->upd();
  return p;
}
inline void link(node *x,node *y) { x->f=y; expose(x); }
inline void cut(node *x){ expose(x); splay(x); x->ch[0]->f=NULL; x->ch[0]=NULL; x->upd(); }
inline int query(node *x){ expose(x); splay(x); return x->s; }

int n,m;

struct event{
  int f,t,x,y,z;
  event(int f=0,int t=0,int x=0,int y=0,int z=0):f(f),t(t),x(x),y(y),z(z) { }
  bool operator < (const event &B) const{
    return t==B.t?f<B.f:t<B.t;
  }
}eve[N]; int tot;
int ans[N],idx;

int fat[N],cur;
const int B=2e5;
int lp[N],rp[N];

int main(){
  int order,cur,l,r,x,y,z; node *lca;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n); read(m);
  cur=1; int cnt=1; lp[1]=1; rp[1]=n;
  pool[1].v=pool[1].s=1;
  link(pool+B+cur,pool+1);
  for (int i=1;i<=m;i++){
    read(order);
    if (order==0){
      read(l); read(r);
      ++cnt; pool[cnt].s=pool[cnt].v=1;
      lp[cnt]=l; rp[cnt]=r;
      link(pool+cnt,pool+B+cur);
    }else if (order==1){
      read(l); read(r); read(x);
      l=max(l,lp[x]); r=min(r,rp[x]);
      if (l<=r){
    ++cur;
    link(pool+B+cur,pool+B+cur-1);
    eve[++tot]=event(1,l,cur,x);
    eve[++tot]=event(0,r+1,cur,x);
      }
    }else{
      read(x); read(l); read(r);
      eve[++tot]=event(2,x,l,r,++idx);
    }
  }
  sort(eve+1,eve+tot+1);
  for (int i=1;i<=tot;i++)
    if (eve[i].f==1){
      x=eve[i].x; y=eve[i].y;
      cut(pool+B+x);
      link(pool+B+x,pool+y);
    }else if (eve[i].f==0){
      x=eve[i].x; y=eve[i].y;
      cut(pool+B+x);
      link(pool+B+x,pool+B+x-1);
    }else{
      x=eve[i].x; y=eve[i].y; z=eve[i].z;
      expose(pool+x); splay(pool+x); ans[z]+=pool[x].s;
      lca=expose(pool+y); splay(pool+y); ans[z]+=pool[y].s;
      expose(lca); splay(lca); ans[z]-=(lca->s)<<1;
    }
  for (int i=1;i<=idx;i++)
    printf("%d\n",ans[i]);
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值