Live2d Test Env

BZOJ -3730(动态点分治)

题目:在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

思路:点分树,动态维护一个重心的信息。 这里维护的是点到其他点的某距离下的权值和。 注意处理重复信息。

时间卡得有点紧,ST表求LCA,没树剖快。。。居然?

线段树没树状数组快,这个可以理解,关键是在于怎么开点,不会炸空间--------把空间和点分树的对应起来O(NlogN)就可以了。

 

(T了很多次,也改(抄)了不少写法,日后再来补。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,m,V[MAX];
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
/********************************************************************/
/*int size[MAX],dfn[MAX],top[MAX],dep[MAX],fa[MAX],tim,hson[MAX];
void dfs1(int u,int ff)
{
    fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;if(v==ff)continue;
        dfs1(v,u);size[u]+=size[v];
        if(size[v]>size[hson[u]])hson[u]=v;
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    if(hson[u])dfs2(hson[u],tp);
    for(int i=h[u];i;i=e[i].next)
        if(e[i].v!=fa[u]&&e[i].v!=hson[u])
            dfs2(e[i].v,e[i].v);
}
int LCA(int u,int v)
{
    while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
    return dep[u]<dep[v]?u:v;
}
int Dis(int u,int v){return dep[u]+dep[v]-2*dep[LCA(u,v)];}*/
bool vis[MAX];
int ver[MAX<<1],first[MAX<<1],dept[MAX<<1],Tot;
int dp[MAX<<1][21],dep[MAX<<1];
void dfs(int u ,int d)
{
    vis[u]=true;
    ver[++Tot] = u;
    first[u] = Tot;
    dept[Tot] = d; dep[u]=d;
   for(int i=h[u];i;i=e[i].next)
        if( !vis[e[i].v] )
        {
            dfs(e[i].v,d+1);
            ver[++Tot] = u;
            dept[Tot] = d;
        }
}

void ST(int N)
{
    for(int i=1;i<=N;i++)  dp[i][0] = i;
    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=1;i+(1<<j)-1<=N;i++)
        {
            int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];
            dp[i][j] = dept[a]<dept[b]?a:b;
        }
    }
}
int lg2[MAX<<1];
int RMQ(int l,int r)
{
    int k=0;
    //while((1<<(k+1))<=r-l+1)  k++;
    k=lg2[r-l+1];
    int a=dp[l][k],b=dp[r-(1<<k)+1][k];
    return dept[a]<dept[b]?a:b;
}

int LCA(int u ,int v)
{
    int x = first[u] , y = first[v];
    int res;
    if(x<=y) res = RMQ(x,y);
    else res=RMQ(y,x);
    //cout<<u<<" "<<v<<" : "<<ver[res]<<endl;
    return ver[res];
}
int Dis(int u,int v)
{
    return dep[u]+dep[v]-(dep[LCA(u,v)]<<1);
}
namespace BIT{
    typedef vector<int> vec;
    struct BIT{
        vec tree; int n;
        inline void init(int size) {tree.resize(size+2); n=size+1;}
        inline int lowbit(int x) {return x&-x;}
        inline void Modify(int x,int d) {if (x<=0) return; for (int i=x; i<=n; i+=lowbit(i)) tree[i]+=d;}
        inline int Query(int x) {int re=0; if (x>n) x=n; for (int i=x; i>0; i-=lowbit(i)) re+=tree[i]; return re;}
    }G[MAX<<1];
}using namespace BIT;
int Fa[MAX],Size,root,mx,size[MAX];
void Getroot(int u,int ff)
{
    size[u]=1;int ret=0;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;if(v==ff||vis[v])continue;
        Getroot(v,u);size[u]+=size[v];
        ret=max(ret,size[v]);
    }
    ret=max(ret,Size-size[u]);
    if(ret<mx)mx=ret,root=u;
}
void DFS(int u,int ff)
{
    vis[u]=true;Fa[u]=ff;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;if(vis[v])continue;
        mx=Size=size[v];
        Getroot(v,u);
        G[root].init(Size); G[root+n].init(Size);
        DFS(root,u);
    }
}
void Modify(int x,int w)
{
    G[x].Modify(1,w);
    for(int i=x;Fa[i];i=Fa[i])
    {
        int dis=Dis(x,Fa[i]);
        G[Fa[i]].Modify(dis+1,w);
        G[i+n].Modify(dis+1,w);
    }
}
int Query(int x,int K)
{
    int ret=G[x].Query(K+1);
    for(int i=x;Fa[i];i=Fa[i])
    {
        int dis=Dis(x,Fa[i]);if(dis>K)continue;
        //ret+=Query(rt[Fa[i]],0,n,0,K-dis);
        //ret-=Query(rt[i+n],0,n,0,K-dis);
        ret+=G[Fa[i]].Query(K-dis+1);
        ret-=G[i+n].Query(K-dis+1);
    }
    return ret;
}
/********************************************************************/
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)V[i]=read();
    for(int i=1;i<n;++i)
    {
        int u=read(),v=read();
        Add(u,v);Add(v,u);
    }
    /*dfs1(1,0);dfs2(1,1);*/
    dfs(1,0);
    ST(Tot);
    lg2[0]=-1;
    for(int i=1;i<=Tot;i++) lg2[i]=lg2[i>>1]+1;
    for(int i=1;i<=n;i++) vis[i]=0;
    Size=mx=n;
    Getroot(1,0); G[root].init(n); G[root+n].init(n);DFS(root,0);
    for(int i=1;i<=n;++i) Modify(i,V[i]);
    int ans=0;
    while(m--)
    {
        int opt=read(),x=read()^ans,y=read()^ans;
        if(opt==0)printf("%d\n",ans=Query(x,y));
        else Modify(x,y-V[x]),V[x]=y;
    }
    return 0;
}

 

posted @ 2019-07-12 11:31  nimphy  阅读(242)  评论(0编辑  收藏  举报