[环套树 bfs序] ICPC 2016 Shenyang J & HDU5957 Query on a graph

6 篇文章 0 订阅
5 篇文章 0 订阅

按层建线段树,或者说是bfs序。
然后修改的一定是不超过5层里面的连续的段,可以在线段树上直接修改。
对于环+树,把环抠出来之后按树的方法做。

代码丑

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;

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;
}
inline void read(char &x){
  for (x=nc();!(x>='A' && x<='Z');x=nc());
}

const int N=100005;

namespace BIT{
  int maxn; ll c1[N],c2[N];
  inline void init(int n){
    maxn=n; for (int i=1;i<=n;i++) c1[i]=c2[i]=0;
  }
  inline void add(int x,int d){
    for (int i=x;i<=maxn;i+=i&-i)
      c1[i]+=d,c2[i]+=x*d;
  }
  inline void add(int l,int r,int d){
    if (l>r) return;
    add(l,d); add(r+1,-d);
  }
  inline ll sum(int x){
    ll ret1=0,ret2=0;
    for (int i=x;i;i-=i&-i)
      ret1+=c1[i],ret2+=c2[i];
    return ret1*(x+1)-ret2;
  }
  inline ll sum(int l,int r){
    if (l>r) return 0;
    return sum(r)-sum(l-1);
  }
}

struct edge{
  int u,v,next;
}G[N<<1];
int head[N],inum;
inline void edd(int u,int v,int p){
  G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}

int inp[N],pth[N];
int fat[N],depth[N];
#define V G[p].v
inline void dfs(int u,int fa){
  fat[u]=fa; depth[u]=depth[fa]+1;
  for (int p=head[u];p;p=G[p].next)
    if (V!=fa)
      if (!depth[V])
    dfs(V,u);
      else if (depth[V]<depth[u]){
    int t=u;
    while (t!=V)
      pth[++*pth]=t,inp[t]=*pth,t=fat[t];
    pth[++*pth]=t,inp[t]=*pth;
      }
}

int n;
int rt[N];
int clk,pre[N],lp[N],rp[N],lp2[N],rp2[N];

int l,r,Q[N];
inline void bfs(int S){
  l=r=0; Q[++r]=S; fat[S]=0; depth[S]=0; pre[S]=++clk;
  while (l<r){
    int u=Q[++l];
    for (int p=head[u];p;p=G[p].next)
      if (V!=fat[u] && !inp[V])
    Q[++r]=V,pre[V]=++clk,fat[V]=u,depth[V]=depth[u]+1;
  }
  for (int i=r;i;i--){
    int u=Q[i],fa=fat[u];
    rt[u]=S;
    if (!fa) continue;
    lp[fa]=min(lp[fa],pre[u]);
    rp[fa]=max(rp[fa],pre[u]);
    lp2[fa]=min(lp2[fa],lp[u]);
    rp2[fa]=max(rp2[fa],rp[u]);
  }
}

inline int Pre(int x){ return pth[inp[x]==1?*pth:inp[x]-1]; }
inline int Nxt(int x){ return pth[inp[x]==*pth?1:inp[x]+1]; }

int vst[N];

inline void Add(int x,int d,int k){
  int fa=fat[x];
  using namespace BIT;
  if (d==0){
    add(pre[x],pre[x],k);
  }else if (d==1){
    add(lp[x],rp[x],k);
    add(pre[x],pre[x],k);
    if (depth[x]>0){
      add(pre[fa],pre[fa],k);
    }else{
      add(pre[Pre(x)],pre[Pre(x)],k);
      add(pre[Nxt(x)],pre[Nxt(x)],k);
    }
  }else{
    add(lp2[x],rp2[x],k);
    add(lp[x],rp[x],k);
    if (depth[x]>1){
      add(lp[fa],rp[fa],k);
      add(pre[fa],pre[fa],k);
      add(pre[fat[fa]],pre[fat[fa]],k);
    }else if (depth[x]==1){
      add(lp[fa],rp[fa],k);
      add(pre[fa],pre[fa],k);
      add(pre[Pre(fa)],pre[Pre(fa)],k);
      add(pre[Nxt(fa)],pre[Nxt(fa)],k);
    }else if (depth[x]==0){
      add(pre[x],pre[x],k);
      add(pre[Pre(x)],pre[Pre(x)],k);
      add(lp[Pre(x)],rp[Pre(x)],k);
      add(pre[Nxt(x)],pre[Nxt(x)],k);
      add(lp[Nxt(x)],rp[Nxt(x)],k);
      vst[x]=vst[Pre(x)]=vst[Nxt(x)]=1;
      int t1,t2;
      if (!vst[t1=Pre(Pre(x))])
    add(pre[t1],pre[t1],k),vst[t1]=1;
      if (!vst[t2=Nxt(Nxt(x))])
    add(pre[t2],pre[t2],k),vst[t2]=1;
      vst[x]=vst[Pre(x)]=vst[Nxt(x)]=vst[t1]=vst[t2]=0;
    }
  }
}

inline ll Sum(int x,int d){
  ll ret=0;

  int fa=fat[x];
  using namespace BIT;
  if (d==0){
    ret+=sum(pre[x],pre[x]);
  }else if (d==1){
    ret+=sum(lp[x],rp[x]);
    ret+=sum(pre[x],pre[x]);
    if (depth[x]>0){
      ret+=sum(pre[fa],pre[fa]);
    }else{
      ret+=sum(pre[Pre(x)],pre[Pre(x)]);
      ret+=sum(pre[Nxt(x)],pre[Nxt(x)]);
    }
  }else{
    ret+=sum(lp2[x],rp2[x]);
    ret+=sum(lp[x],rp[x]);
    if (depth[x]>1){
      ret+=sum(lp[fa],rp[fa]);
      ret+=sum(pre[fa],pre[fa]);
      ret+=sum(pre[fat[fa]],pre[fat[fa]]);
    }else if (depth[x]==1){
      ret+=sum(lp[fa],rp[fa]);
      ret+=sum(pre[fa],pre[fa]);
      ret+=sum(pre[Pre(fa)],pre[Pre(fa)]);
      ret+=sum(pre[Nxt(fa)],pre[Nxt(fa)]);
    }else if (depth[x]==0){
      ret+=sum(pre[x],pre[x]);
      ret+=sum(pre[Pre(x)],pre[Pre(x)]);
      ret+=sum(lp[Pre(x)],rp[Pre(x)]);
      ret+=sum(pre[Nxt(x)],pre[Nxt(x)]);
      ret+=sum(lp[Nxt(x)],rp[Nxt(x)]);
      vst[x]=vst[Pre(x)]=vst[Nxt(x)]=1;
      int t1,t2;
      if (!vst[t1=Pre(Pre(x))])
    ret+=sum(pre[t1],pre[t1]),vst[t1]=1;
      if (!vst[t2=Nxt(Nxt(x))])
    ret+=sum(pre[t2],pre[t2]),vst[t2]=1;
      vst[x]=vst[Pre(x)]=vst[Nxt(x)]=vst[t1]=vst[t2]=0;
    }
  }

  return ret;
}

int main(){
  int T,Q,iu,iv,k; char order;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  while (T--){
    read(n);
    for (int i=1;i<=n;i++) head[i]=0; inum=0;
    for (int i=1;i<=n;i++) read(iu),read(iv),edd(iu,iv,++inum),edd(iv,iu,++inum);
    for (int i=1;i<=n;i++) depth[i]=0,inp[i]=0;
    *pth=0; dfs(1,0);
    for (int i=1;i<=n;i++) lp[i]=lp2[i]=n+1,rp[i]=rp2[i]=0;
    clk=0;
    for (int i=1;i<=n;i++) fat[i]=depth[i]=0;
    for (int i=1;i<=*pth;i++) bfs(pth[i]);
    BIT::init(n);
    read(Q);
    while (Q--){
      read(order); read(iu); read(iv);
      if (order=='M') read(k),Add(iu,iv,k);
      else printf("%I64d\n",Sum(iu,iv));
    }
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值