HDU 5029 Relief grain(恶心的树链剖分 + 线段树)

来源:互联网 发布:趣头条提现是骗局 知乎 编辑:程序博客网 时间:2024/04/30 23:32

题意:

n个村庄分配粮食,m次分配,每一次分配树上的l~r区间村庄内某种粮食*1,询问每个村庄最多粮食数量的种类是什么


分析:

首先注意到题目要求在树上的路径分配粮食,很容易想到用树链剖分和线段树去处理区间查找过程

如果此时强行将每个区间内的粮食数量及种类全部存下来,很明显内存会爆掉,试过了。。。

此处则行不通,也是关键要解决的问题

稍微观察一下,注意到没有更新操作,完全可以离线,很快发现其实对于粮食的分配可以根据种类排序

由于每个村庄的答案唯一,并且在后一种类来之前,前一种类的粮食一定是分配完成的,那么此时在线段树上递归pushdown就能不断更新最大种类的粮食


C++ 提交 4992ms 强行卡过 排名最后。。。(谁让我懒,用vector呢。。。)


#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 200005int n,m;int x[maxn],y[maxn],c[maxn];int fir[maxn],v[maxn],nex[maxn],e_max;int son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],pos[maxn],tot;int L[2*maxn],R[2*maxn];int now;vector<int>vec[2*maxn],num[2*maxn],tmp,tmp1;int lazy[2*maxn];int e[maxn];void init_(){    memset(son,-1,sizeof son);    memset(siz,0,sizeof siz);    memset(fir,-1,sizeof fir);    tot=1;    e_max=0;    now=0;}void add_edge(int s,int t){    int e=e_max++;    v[e]=t;    nex[e]=fir[s];    fir[s]=e;}bool cmp(int a,int b){    return c[a]<c[b];}void dfs1(int k,int pre,int d){    deep[k]=d;    fa[k]=pre;    siz[k]++;    for(int i=fir[k]; ~i; i=nex[i])    {        int r=v[i];        if(r!=pre)        {            dfs1(r,k,d+1);            siz[k]+=siz[r];            if(son[k]==-1||siz[son[k]]<siz[r]) son[k]=r;        }    }}void dfs2(int k,int sp){    top[k]=sp;    pos[k]=tot++;    if(son[k]==-1) return ;    dfs2(son[k],sp);    for(int i=fir[k]; ~i; i=nex[i])    {        int r=v[i];        if(r!=fa[k]&&r!=son[k])        {            dfs2(r,r);        }    }}void init(int l,int r,int k){    L[k]=l;    R[k]=r;    vec[k].clear();    num[k].clear();    lazy[k]=0;    if(l==r) return ;    int mid=l+r>>1;    init(l,mid,k<<1);    init(mid+1,r,k<<1|1);}void special(int k,int d,int n){    if(vec[k].size()==0)    {        vec[k].push_back(d);        num[k].push_back(n);        lazy[k]=d;        return ;    }    if(vec[k].size()==1||lazy[k]==d)    {        if(vec[k][0]==d)        {            num[k][0]+=n;        }        else        {            vec[k].push_back(d);            num[k].push_back(n);            if(num[k][1]>num[k][0])            {                swap(num[k][0],num[k][1]);                swap(vec[k][0],vec[k][1]);                lazy[k]=vec[k][0];                vec[k].resize(1);                num[k].resize(1);            }        }        return ;    }    if(vec[k][1]==d)    {        num[k][1]+=n;        if(num[k][1]>num[k][0])        {            swap(num[k][0],num[k][1]);            swap(vec[k][0],vec[k][1]);            lazy[k]=vec[k][0];            vec[k].resize(1);            num[k].resize(1);        }    }    else    {        if(num[k][1]>num[k][0])        {            swap(num[k][0],num[k][1]);            swap(vec[k][0],vec[k][1]);            lazy[k]=vec[k][0];        }        vec[k].resize(1);        num[k].resize(1);        vec[k].push_back(d);        num[k].push_back(n);        if(num[k][1]>num[k][0])        {            swap(num[k][0],num[k][1]);            swap(vec[k][0],vec[k][1]);            lazy[k]=vec[k][0];            vec[k].resize(1);            num[k].resize(1);        }    }}void Resize(int d,int n,int k){    if(L[k]==R[k])    {        special(k,d,n);        return ;    }    if(vec[k].size()==0)    {        vec[k].push_back(d);        num[k].push_back(n);        lazy[k]=d;        return ;    }    if(lazy[k]==d)    {        num[k][0]+=n;        return ;    }    if(num[k][0]>=n&&now!=d) return ;    Resize(vec[k][0],num[k][0],k<<1);    Resize(vec[k][0],num[k][0],k<<1|1);    vec[k].clear();    num[k].clear();    vec[k].push_back(d);    num[k].push_back(n);    lazy[k]=d;}void pushdown(int k){    if(vec[k].size()==0) return ;    Resize(vec[k][0],num[k][0],k<<1);    Resize(vec[k][0],num[k][0],k<<1|1);    vec[k].clear();    num[k].clear();    lazy[k]=0;}void update(int d,int s,int t,int l,int r,int k){    if(s==l&&r==t)    {        if(s==t)        {            special(k,d,1);        }        else if(lazy[k]==0)        {            vec[k].push_back(d);            num[k].push_back(1);            lazy[k]=d;        }        else if(lazy[k]==d)        {            num[k][0]++;        }        else        {            pushdown(k);            vec[k].push_back(d);            num[k].push_back(1);            lazy[k]=d;        }        return ;    }    pushdown(k);    int mid=l+r>>1;    if(t<=mid) update(d,s,t,l,mid,k<<1);    else if(s>mid) update(d,s,t,mid+1,r,k<<1|1);    else    {        update(d,s,mid,l,mid,k<<1);        update(d,mid+1,t,mid+1,r,k<<1|1);    }}void query(int d,int l,int r,int k){    if(l==d&&r==d)    {        tmp=vec[k];        tmp1=num[k];        return ;    }    pushdown(k);    int mid=l+r>>1;    if(d<=mid) query(d,l,mid,k<<1);    else query(d,mid+1,r,k<<1|1);}void Change(int s,int t,int r){    int f1=top[s],f2=top[t];    while(f1!=f2)    {        if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t);        update(r,pos[f1],pos[s],1,tot-1,1);        s=fa[f1];        f1=top[s];    }    if(deep[s]>deep[t]) swap(s,t);    update(r,pos[s],pos[t],1,tot-1,1);}int main(){    while(scanf("%d%d",&n,&m)!=EOF&&n+m)    {        init_();        for(int i=1; i<n; i++)        {            int a,b;            scanf("%d%d",&a,&b);            add_edge(a,b);            add_edge(b,a);        }        for(int i=0; i<m; i++)        {            scanf("%d%d%d",&x[i],&y[i],&c[i]);            e[i]=i;        }        dfs1(1,-1,1);        dfs2(1,1);        init(1,tot-1,1);        sort(e,e+m,cmp);        for(int i=0; i<m; i++)        {            int r=e[i];            now=c[r];            Change(x[r],y[r],c[r]);        }        for(int i=1; i<=n; i++)        {            query(pos[i],1,tot-1,1);            int val=0;            int sum=0;            for(int j=0; j<tmp.size(); j++)            {                if(tmp1[j]>sum) sum=tmp1[j],val=tmp[j];            }            printf("%d\n",val);        }    }    return 0;}/*5 41 22 33 44 51 5 11 3 21 2 21 1 39 171 21 32 42 58 49 46 37 34 5 15 4 14 5 14 5 25 4 25 4 25 4 24 5 34 5 34 5 34 5 34 8 44 8 44 8 44 8 44 8 48 4 4*/


0 0
原创粉丝点击