如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1553

来自"NOCOW"

跳转到: 导航, 搜索

哎,第一次写树的剖分,代码好乱啊。。。

复杂度是O(n*log(n)*log(n))。

好像可以写动态树,复杂度是O(n*log(n))。

还是太水了啊。

#include <cstdio>
#include <cstring>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
const int maxn=100010,maxm=(maxn<<1),INF=0x7FFFFFFF;
int tot,dep,res,total,anc[maxm<<2];
int head[maxn],node[maxm],next_h[maxm],order[maxm];
int pos[maxn],size[maxn],level[maxn],father[maxn];
int h[maxn],stk_x[maxn],stk_fa[maxn],stk_lvl[maxn];
bool vis[maxn],used[maxn],stk_flag[maxn];
pair<int,int> P[maxn];
class segmenttree
{
    private:
    vector<int> tree;
    int res,dep,size;
    public:
    void clear()  {  size=0;  }
    segmenttree()  {  clear();  }
    int start;
    void insert(int x)
    {
        if (!size)  start=x;
        used[x]=true;
        P[x].first=total;
        P[x].second=++size;
    }
    void build()
    {
        int i;
        for (dep=0;(1<<dep)<(size<<1);++dep);
        res=(1<<dep-1)-1;
        tree.resize(1<<dep|1);
        for (i=0;i<=(1<<dep);++i)  tree[i]=0;
    }
    void modify(int x,int delta)
    {
        x+=res;
        tree[x]+=delta;
        for (x>>=1;x;x>>=1)
            tree[x]=max(tree[x<<1],tree[x<<1|1]);
    }
    int ask(int l,int r)
    {
        int tmp=0;
        l+=res,r+=res;
        if (l > r)  swap(l,r);
        if (l == r)  return tree[l];
        l==res+1?tmp=max(tmp,tree[l]):--l;
        r==res+size?tmp=max(tmp,tree[r]):++r;
        for (;l^r^1;l>>=1,r>>=1)
        {
            if (~l&1)  tmp=max(tmp,tree[l^1]);
            if (r&1)  tmp=max(tmp,tree[r^1]);
        }
        return tmp;
    }
}_st;
vector<segmenttree> st;
void addedge(int a,int b)
{
    node[++tot]=b;
    next_h[tot]=head[a];
    head[a]=tot;
}
void dfs(int x,int fa,int lvl)
{
    int top,y;
    memset(pos,0,sizeof(pos));
    memset(vis,false,sizeof(vis));
    memcpy(h,head,sizeof(head));
    tot=0,top=1;
    stk_x[1]=x,stk_fa[1]=fa,stk_lvl[1]=lvl;
    while (top)
    {
        x=stk_x[top],lvl=stk_lvl[top];
        vis[x]=true;
        order[++tot]=x;
        if (!pos[x])
        {
            size[x]=1;
            pos[x]=tot;
            father[x]=stk_fa[top];
            level[x]=lvl;
        }
        y=node[h[x]];
        if (h[x] && vis[y] && (y != father[x]))  size[x]+=size[y];
        for (;h[x]&&vis[node[h[x]]];h[x]=next_h[h[x]]);
        if (!h[x])  --top;
        else
        {
            y=node[h[x]];
            stk_x[++top]=y,stk_fa[top]=x,stk_lvl[top]=lvl+1;
        }
    }
    level[0]=INF;
}
void subdiv(int x,int flag)
{
    int top,y,i,w,maxs;
    memset(vis,false,sizeof(vis));
    memset(used,false,sizeof(used));
    memcpy(h,head,sizeof(head));
    total=-1,top=1;
    stk_x[1]=x,stk_flag[1]=flag;
    while (top)
    {
        x=stk_x[top],flag=stk_flag[top];
        vis[x]=true;
        if (!used[x])
        {
            if (flag)  ++total,_st.clear();
            _st.insert(x);
            if ((!next_h[head[x]]) && (node[head[x]] == father[x]))
            {
                st.push_back(_st);
                --top;
                continue;
            }
            for (maxs=0,i=head[x];i;i=next_h[i])
            {
                y=node[i];
                if (vis[y])  continue;
                if (size[y] > maxs)  maxs=size[y],w=y;
            }
            stk_x[++top]=w,stk_flag[top]=false;
        }
        else
        {
            for (;h[x]&&vis[node[h[x]]];h[x]=next_h[h[x]]);
            if (!h[x])  --top;
            else  stk_x[++top]=node[h[x]],stk_flag[top]=true;
        }
    }
}
void init()
{
    int i,n,u,v;
    scanf("%d",&n);
    tot=0;
    memset(head,0,sizeof(head));
    memset(size,0,sizeof(size));
    memset(anc,0,sizeof(anc));
    for (i=1;i<n;++i)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    dfs(1,0,1);
    for (dep=0;(1<<dep)<(tot<<1);++dep);
    res=(1<<dep-1)-1;
    for (i=1;i<=tot;++i)  anc[i+res]=order[i];
    for (--dep;dep;--dep)
        for (i=(1<<dep-1);i<(1<<dep);++i)
            if (level[anc[i<<1]] < level[anc[i<<1|1]])
                anc[i]=anc[i<<1];
            else
                anc[i]=anc[i<<1|1];
    st.clear();
    for (i=0;i<=n;++i)  P[i].first=P[i].second=-1;
    subdiv(1,true);
    for (i=0;i<=total;++i)  st[i].build();
}
int lca(int l,int r)
{
    int co_anc=0;
    l=pos[l]+res,r=pos[r]+res;
    if (r < l)  swap(l,r);
    if (l == r)  return anc[l];
    if (l == res+1)
    {
        if (level[anc[l]] < level[co_anc])
            co_anc=anc[l];
    }
    else  --l;
    if (r == res+tot)
    {
        if (level[anc[r]] < level[co_anc])
            co_anc=anc[r];
    }
    else  ++r;
    for (;l^r^1;l>>=1,r>>=1)
    {
        if (~l&1)
            if (level[anc[l^1]] < level[co_anc])
                co_anc=anc[l^1];
        if (r&1)
            if (level[anc[r^1]] < level[co_anc])
                co_anc=anc[r^1];
    }
    return co_anc;
}
int count(int x,int fa)
{
    int tmp=0,y;
    for (;x&&(level[x]>=level[fa]);x=father[y])
    {
        y=st[P[x].first].start;
        if (level[y] < level[fa])
            tmp=max(tmp,st[P[x].first].ask(P[x].second,P[fa].second));
        else
            tmp=max(tmp,st[P[x].first].ask(P[x].second,P[y].second));
    }
    return tmp;
}
void solve()
{
    int i,Q,u,v,fa,ans;
    char ch;
    scanf("%d%*c",&Q);
    for (i=1;i<=Q;++i)
    {
        scanf("%c%d%d%*c",&ch,&u,&v);
        if (ch == 'I')  st[P[u].first].modify(P[u].second,v);
        else
        {
            fa=lca(u,v);
            ans=st[P[fa].first].ask(P[fa].second,P[fa].second);
            ans=max(ans,count(u,fa));
            ans=max(ans,count(v,fa));
            printf("%d\n",ans);
        }
    }
}
int main()
{
    init();
    solve();
    return 0;
}
//by zzy
个人工具