BZOJ1036: [ZJOI2008]树的统计Count

来源:互联网 发布:linux 更改机器名称 编辑:程序博客网 时间:2024/06/05 12:00

题目链接

单点修改,区间最大值,区间和。
树链剖分裸的不能再裸了。
LCT也可以完成。

1.树链剖分

#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 30005 #define M 200005#define INF 1e9#define mod 1000000using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){    int x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}int n,m,cnt,ind,T;int b[N<<1],p[N],nextedge[N<<1];int deep[N],fa[N],son[N],sz[N],pos[N],ftree[N],top[N],a[N];class Seg_Tree{    public:        int l,r,mx,sum;}e[N<<2];void Add(int x,int y){    cnt++;    b[cnt]=y;    nextedge[cnt]=p[x];    p[x]=cnt;}void Anode(int x,int y){    Add(x,y);Add(y,x);}void Input_Init(){    n=read();    for(int i=1;i<n;i++)    {        static int x,y;        x=read(),y=read();        Anode(x,y);    }    for(int i=1;i<=n;i++) a[i]=read();}void Dfs(int x){    sz[x]=1;    for(int i=p[x];i;i=nextedge[i])    {        int v=b[i];        if(v==fa[x]) continue;        deep[v]=deep[x]+1;fa[v]=x;        Dfs(v);sz[x]+=sz[v];        son[x]=sz[son[x]]>sz[v]?son[x]:v;    }}void dfs(int x,int root){    pos[x]=++ind;ftree[pos[x]]=x;    top[x]=root;    if(!son[x]) return;    dfs(son[x],root);    for(int i=p[x];i;i=nextedge[i])    {        int v=b[i];        if(v!=fa[x]&&v!=son[x]) dfs(v,v);    }}void pushup(int p){    e[p].mx=max(e[p<<1].mx,e[p<<1|1].mx);    e[p].sum=e[p<<1].sum+e[p<<1|1].sum;}void Build(int p,int l,int r){    e[p].l=l,e[p].r=r;    if(l==r)    {        e[p].mx=e[p].sum=a[ftree[l]];        return;    }    int mid=l+r>>1;    Build(p<<1,l,mid);Build(p<<1|1,mid+1,r);    pushup(p);}void Solve_Change(int p,int x,int y){    int l=e[p].l,r=e[p].r,mid=l+r>>1;    if(l==x&&r==x)    {        e[p].mx=e[p].sum=y;        return;    }    if(x<=mid) Solve_Change(p<<1,x,y);    else Solve_Change(p<<1|1,x,y);    pushup(p);}int Query_Max(int p,int x,int y){    int l=e[p].l,r=e[p].r,mid=l+r>>1;    if(l==x&&y==r)        return e[p].mx;    if(y<=mid) return Query_Max(p<<1,x,y);    if(x>mid) return Query_Max(p<<1|1,x,y);    return max(Query_Max(p<<1,x,mid),Query_Max(p<<1|1,mid+1,y));}void Solve_Max(int x,int y){    int fx=top[x],fy=top[y];    int rtn=-INF;    while(fx!=fy)    {        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);        rtn=max(rtn,Query_Max(1,pos[fx],pos[x]));        x=fa[fx],fx=top[x];    }    if(deep[x]<deep[y]) swap(x,y);    rtn=max(rtn,Query_Max(1,pos[y],pos[x]));    printf("%d\n",rtn);}int Query_Sum(int p,int x,int y){    int l=e[p].l,r=e[p].r,mid=l+r>>1;    if(l==x&&y==r)        return e[p].sum;    if(y<=mid) return Query_Sum(p<<1,x,y);    if(x>mid) return Query_Sum(p<<1|1,x,y);    return Query_Sum(p<<1,x,mid)+Query_Sum(p<<1|1,mid+1,y);}void Solve_Sum(int x,int y){    int fx=top[x],fy=top[y];    int rtn=0;    while(fx!=fy)    {        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);        rtn+=Query_Sum(1,pos[fx],pos[x]);        x=fa[fx],fx=top[x];    }    if(deep[x]<deep[y]) swap(x,y);    rtn+=Query_Sum(1,pos[y],pos[x]);    printf("%d\n",rtn);}void Solve(){    m=read();    char ch[10];static int x,y;    while(m--)    {        scanf("%s",ch);x=read(),y=read();        if(ch[1]=='M') Solve_Max(x,y);        else if(ch[1]=='S') Solve_Sum(x,y);        else Solve_Change(1,pos[x],y);    }}int main(){    Input_Init();     Dfs(1);dfs(1,1);Build(1,1,n);    Solve();    return 0;}

刚学LCT。。拿来练习一下。(但是比树链剖分慢很多╮(╯▽╰)╭)
2.LCT

#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 30005 #define M 2001005#define INF 1e9using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){    int x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}int n,m,top,cnt;int b[N<<1],p[N],nextedge[N<<1];int mx[N],tag[N],a[N],son[N][2],st[N],fa[N],sum[N];bool rev[N];void Add(int x,int y){    cnt++;    b[cnt]=y;    nextedge[cnt]=p[x];    p[x]=cnt;}void Anode(int x,int y){    Add(x,y);Add(y,x);}void dfs(int x){    for(int i=p[x];i;i=nextedge[i])    {        int v=b[i];        if(v==fa[x]) continue;        fa[v]=x;dfs(v);    }}void Input_Init(){    n=read();mx[0]=-INF;    for(int i=1;i<n;i++)    {        static int x,y;        x=read(),y=read();        Anode(x,y);    }    for(int i=1;i<=n;i++) sum[i]=a[i]=mx[i]=read();    dfs(1);}bool isroot(int x){    return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}void pushup(int k){    int l=son[k][0],r=son[k][1];    mx[k]=max(max(mx[l],mx[r]),a[k]);    sum[k]=sum[l]+sum[r]+a[k];}void pushdown(int k){    int l=son[k][0],r=son[k][1];    if(rev[k])    {        rev[k]=0;rev[l]^=1;rev[r]^=1;        swap(son[k][0],son[k][1]);    }}void Rotate(int x){    int y=fa[x],z=fa[y],l,r;    l=son[y][1]==x;r=l^1;    if(!isroot(y)) son[z][son[z][1]==y]=x;    fa[x]=z;fa[y]=x;fa[son[x][r]]=y;    son[y][l]=son[x][r];son[x][r]=y;    pushup(y);pushup(x);}void Splay(int x){    top=0;st[++top]=x;    for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];    while(top) pushdown(st[top--]);    while(!isroot(x))    {        int y=fa[x],z=fa[y];        if(!isroot(y)) {            if(son[z][0]==y^son[y][0]==x) Rotate(x);            else Rotate(y);        }        Rotate(x);    }}void Access(int x){    for(int t=0;x;t=x,x=fa[x])        Splay(x),son[x][1]=t,pushup(x);}void Make_Root(int x){    Access(x);Splay(x);rev[x]^=1;}void Solve_Change(int x,int y){    Splay(x);mx[x]=sum[x]=a[x]=y;    pushup(x);}void Solve_Max(int x,int y){    Make_Root(x);Access(y);Splay(y);    printf("%d\n",mx[y]);}void Solve_Sum(int x,int y){    Make_Root(x);Access(y);Splay(y);    printf("%d\n",sum[y]);}void Solve(){    m=read();    while(m--)    {        char ch[10];static int x,y;        scanf("%s",ch);x=read(),y=read();        if(ch[0]=='C') Solve_Change(x,y);        else if(ch[1]=='M') Solve_Max(x,y);        else Solve_Sum(x,y);    }}int main(){    Input_Init();    Solve();     return 0;}
0 0
原创粉丝点击