码迷,mamicode.com
首页 > 其他好文 > 详细

求常数优化

时间:2018-02-22 00:20:47      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:std   while   iostream   def   fine   putchar   +=   query   log   

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001

int n,a[N];

int front[N],nxt[N<<1],to[N<<1],tot;

int all,root;
int siz[N],f[N];

bool vis[N];

int dep[N];
int fa[N][18],dis[N][18];

struct Segment
{
    int cnt;
    int rt[N];
    int lc[N*80],rc[N*80],val[N*80];
    
    void Change(int &k,int l,int r,int x,int y)
    {
        if(!k) k=++cnt;
        if(l==r)
        {
            val[k]+=y;
            return;
        }
        int mid=l+r>>1;
        if(x<=mid) Change(lc[k],l,mid,x,y);
        else Change(rc[k],mid+1,r,x,y);
        val[k]=val[lc[k]]+val[rc[k]];
    }
    
    int Query(int k,int l,int r,int x)
    {
        if(!k) return 0;
        if(r<=x) return val[k];
        int mid=l+r>>1;
        if(x<=mid) return Query(lc[k],l,mid,x);
        else return val[lc[k]]+Query(rc[k],mid+1,r,x);
    }
    
}tr,ftr;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

void getroot(int x,int y)
{
    siz[x]=1; f[x]=0;
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=y && !vis[to[i]]) 
        {
            getroot(to[i],x);
            siz[x]+=siz[to[i]];
            f[x]=max(f[x],siz[to[i]]);
        }
    f[x]=max(f[x],all-siz[x]);
    if(f[x]<f[root]) root=x;
}

void cal(int x,int ancestor,int father,int d)
{
    int t;
    for(int i=front[x];i;i=nxt[i])
    {
        t=to[i];
        if(t!=father && !vis[t])
        {
            fa[t][++dep[t]]=ancestor;
            dis[t][dep[t]]=d+1;
            cal(t,ancestor,x,d+1);
        }
    }    
}

void build(int x)
{
    vis[x]=true;
    cal(x,x,0,0);
    int tmp=all;
    for(int i=front[x];i;i=nxt[i])
        if(!vis[to[i]])
        {
            all=siz[to[i]];
            if(all>siz[x]) all=tmp-siz[x];
            root=0;
            getroot(to[i],0);
            build(root);
        }
}

void change(int x,int y)
{
    tr.Change(tr.rt[x],0,n-1,0,y);
    int d;
    for(int i=dep[x];i;--i)
    {
        ftr.Change(ftr.rt[fa[x][i+1]],0,n-1,dis[x][i],y);
    //    printf("kk %d\n",dis[x][i]);
        tr.Change(tr.rt[fa[x][i]],0,n-1,dis[x][i],y);
    }
}

int query(int x,int d)
{
    int ans=tr.Query(tr.rt[x],0,n-1,d);
    for(int i=dep[x];i;--i)
    {
        if(d-dis[x][i]>=0) ans+=tr.Query(tr.rt[fa[x][i]],0,n-1,d-dis[x][i]);
        if(d-dis[x][i]>=0) ans-=ftr.Query(ftr.rt[fa[x][i+1]],0,n-1,d-dis[x][i]);
    }
    return ans;
}

void out(int x)
{
    if(x>=10) out(x/10);
    putchar(x%10+0);
}

int main()
{
    //freopen("data.in","r",stdin);
    //freopen("my.out","w",stdout); 
    int m;
    read(n); read(m);
    for(int i=1;i<=n;++i) read(a[i]);
    int u,v;
    for(int i=1;i<n;++i)
    {
        read(u); read(v);
        add(u,v);
    }
    f[0]=n+1;
    all=n;
    getroot(1,0);
    build(root);
    for(int i=1;i<=n;++i) fa[i][dep[i]+1]=i;
    for(int i=1;i<=n;++i) 
    change(i,a[i]);
    int ty,last=0;
    while(m--)
    {
        read(ty); read(u); read(v);
        u^=last; v^=last;
        if(!ty) last=query(u,v),out(last),printf("\n");
        else change(u,v-a[u]),a[u]=v;
    }
    //printf("%d %d",tr.cnt,ftr.cnt);
    return 0;
}

 

求常数优化

标签:std   while   iostream   def   fine   putchar   +=   query   log   

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8457809.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!