[LCT 线段树 dfs序] BZOJ 3779 重组病毒
来源:互联网 发布:什么是java框架 编辑:程序博客网 时间:2024/06/04 18:55
%%%PoPoQQQ http://blog.csdn.net/popoqqq/article/details/45919545
”题目大意:给定一棵树,初始每个点都有一个颜色,支持三种操作:
1.将某个点到根的路径上所有点染上一种新的颜色
2.将某个点到根的路径上所有点染上一种新的颜色,然后把根设为这个点
3.定义一个点的代价为这个点到根路径上颜色的种类数,求某个点子树中所有点代价的平均值
容易发现这玩应就是个LCT,操作1就是Access,操作2就是Move_To_Root,代价就是一个点到根路径上的虚边数量+1
我们用LCT模拟上述操作,用线段树维护DFS序维护信息,一旦LCT中出现了虚实边的切换,就在DFS序上对应的子树+1/-1,查询就直接在线段树上查就行了“
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define V G[p].vusing namespace std;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *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 *s){char c=nc(); int len=0;for (;!(c>='A' && c<='Z');c=nc());for (len=0;c>='A' && c<='Z';s[++len]=c,c=nc()); s[++len]=0;}const int N=100005;namespace BIT{ #define lowbit(x) ((x)&-(x))ll maxn,c1[N],c2[N]; inline void init(int n){ maxn=n; } inline void add(int x,ll r){ for (int i=x;i<=maxn;i+=lowbit(i)) c1[i]+=r,c2[i]+=x*r; } inline void add(int l,int r,ll x){if (l>r) return;add(l,x); add(r+1,-x); }inline ll sum(int x){ll ret1=0,ret2=0;for (int i=x;i;i-=lowbit(i))ret1+=c1[i],ret2+=c2[i];return (x+1)*ret1-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; }; edge G[N*2]; int head[N],inum; inline void add(int u,int v,int p) { G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; }int n,Q,rt;int clk,tid[N],last[N];int fat[N][21],size[N],depth[N];inline void Modify(int x,int val);struct Splay{ struct node{ node *p,*ch[2],*fat; int size,rev,idx; bool dir() { return this==p->ch[1]; } void setc(node *c,int d) { ch[d]=c; c->p=this; } void update(){ size=ch[0]->size+ch[1]->size+1;} void reverse(){ rev^=1; swap(ch[0],ch[1]);}void pushdown(node *null) { if (rev) { if (ch[0]!=null) ch[0]->reverse(); if (ch[1]!=null) ch[1]->reverse(); rev=0; }} }*null; node Mem[N]; Splay(){ null=Mem; null->p=null->ch[0]=null->ch[1]=null; null->size=0; } void rot(node *x){ if (x==null) return; bool d=x->dir(); node *p=x->p; if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null; p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat); } node *stk[N];int pnt; void splay(node *x){ node *y=x; pnt=0; while (y!=null) stk[++pnt]=y,y=y->p; for (int i=pnt;i;i--) stk[i]->pushdown(null); while (x->p!=null) if (x->p->p==null) rot(x); else (x->dir()==x->p->dir())?(rot(x->p),rot(x)):(rot(x),rot(x)); }void Solve(node *x,int val){if (x==null) return; x->pushdown(null);while (x->ch[0]!=null) x=x->ch[0],x->pushdown(null);Modify(x->idx,val);}node *Access(node *x){ node *y=null; while (x!=null) { splay(x); x->ch[1]->p=null; x->ch[1]->fat=x;;Solve(x->ch[1],1);x->setc(y,1); y->fat=null; Solve(y,-1);x->update(); y=x; x=x->fat; } return y; }}LCT; Splay::node *pos[N]; inline void Init(int n){for (int i=1;i<=n;i++) { pos[i]=LCT.Mem+i; pos[i]->size=1; pos[i]->idx=i;pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=pos[i]->fat=LCT.null; } }inline int dfs(int u,int fa) { tid[u]=++clk; size[u]=1; depth[u]=depth[fa]+1; fat[u][0]=fa;for (int k=1;k<=20;k++) fat[u][k]=fat[fat[u][k-1]][k-1];BIT::add(tid[u],tid[u],depth[u]);if (!fa) pos[u]->fat=LCT.null; else pos[u]->fat=pos[fa];for (int p=head[u];p;p=G[p].next)if (V!=fa)size[u]+=dfs(V,u);last[u]=tid[u]+size[u]-1;return size[u];}inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=20;~k;k--) if ((depth[u]-depth[v])&(1<<k)) u=fat[u][k]; if (u==v) return v; for (int k=20;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[u][0];}inline int Fat(int x,int y){for (int k=20;~k;k--)if (depth[fat[x][k]]>depth[y])x=fat[x][k];return x;}inline void Modify(int x,int val){ if(x==rt) { BIT::add(1,n,val); return ; } int lca=LCA(x,rt); if(lca!=x) BIT::add(tid[x],last[x],val); else { int y=Fat(rt,x);BIT::add(1,tid[y]-1,val); BIT::add(last[y]+1,n,val); }}inline ll Sum(int x){if(x==rt) return BIT::sum(1,n); int lca=LCA(x,rt); if(lca!=x) return BIT::sum(tid[x],last[x]); else { int y=Fat(rt,x);return BIT::sum(1,tid[y]-1)+BIT::sum(last[y]+1,n); }}inline ll Size(int x){if(x==rt) return n; int lca=LCA(x,rt); if(lca!=x) return size[x]; else { int y=Fat(rt,x);return n-size[y]; }}int main(){int iu,iv,x; char order[10]; ll ret,tot;freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n); read(Q); Init(n); BIT::init(n);for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);dfs(1,0); rt=1;//for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");while (Q--){read(order); read(x);if (!strcmp(order+1,"RELEASE")){LCT.Access(pos[x]);}else if (!strcmp(order+1,"RECENTER")){LCT.Access(pos[x])->reverse(); rt=x;}else if (!strcmp(order+1,"REQUEST")){ret=Sum(x);tot=Size(x);printf("%.10lf\n",(double)ret/tot);}//for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");}return 0;}
0 0
- BZOJ 3779 重组病毒 LCT+线段树维护DFS序
- [LCT 线段树 dfs序] BZOJ 3779 重组病毒
- BZOJ 3779 重组病毒 LCT维护子树信息
- bzoj3779 lct+线段树+dfs序
- BZOJ 4817 [LCT][线段树][树链剖分]
- bzoj 3306: 树 dfs序+线段树
- BZOJ 1103 DFS序+线段树
- BZOJ 4034 线段树+DFS序
- BZOJ 2819 DFS序+线段树
- BZOJ 3252攻略 dfs序+线段树
- DFS序+线段树(bzoj 4034)
- bzoj 4551(DFS序+线段树)
- 3779: 重组病毒
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
- 【BZOJ 3306】树【LCA、DFS序、线段树】
- BZOJ 4551 树 dfs序+线段树 / 并查集
- 【BZOJ】【P3252】【攻略】【题解】【贪心+dfs序+线段树】
- BZOJ 4034 HAOI2015 T2 DFS序+线段树
- win快捷键大全
- HDOJ(HDU) 2091 空心三角形
- 玩转Google开源C++单元测试框架Google Test系列(gtest)(总)
- 详解HttpURLConnection
- 高精
- [LCT 线段树 dfs序] BZOJ 3779 重组病毒
- Java基础 - 欧几里得法求最大公约数
- JAVA-反射-GETGENERICSUPERCLASS()介绍
- 如何用googletest写单元测试
- Windows10 安装 CentOS7(双系统)
- union和union all的区别
- Android如何在http头信息里设置参数
- myeclipse用maven搭建web项目后tomcat启动报找不到jar包解决办法
- HDU 1166 敌兵布阵