HNOI2015 接水果

Description


 

Input

Output

 

Sample Input

10 10 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
3 2 217394434
10 7 13022269
6 7 283254485
6 8 333042360
4 6 442139372
8 3 225045590
10 4 922205209
10 8 808296330
9 2 486331361
4 9 551176338 
1 8 5
3 8 3
3 8 4
1 8 3
4 8 1
2 3 1
2 3 1
2 3 1
2 4 1
1 4 1

Sample Output

442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434
 

Data Constraint

 
 
 

我们考每个盘子对水果的影响。

每个盘子的路径,我们分两种情况讨论

1.a和b不构成祖先关系

 

那么它能影响的水果必须是起点在a或a的子树,终点在b或b的子树(起终点可调换)
2.a和b构成祖先关系
 那么起点必须在b或b的子树,终点在c的子树之外。
 
我们发现满足要求的起点或终点在dfs序中都是一段连续的区间
 
我们以起点为x轴,终点为y轴,建一个坐标系,我们发现每个盘子对点的要求都可以用一个矩形来表示,每个查询只是查询一点,查询包含它的权值第k小的矩形
我们可以用经典的扫描线问题来解决。
对于y轴,开一个树状数组套权值线段树,支持区间修改和点查询。
 
问题解决,时间复杂度O(Nlog2N)
 
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>

using namespace std;
map<int,int> H;

struct plt{
    int x,z,q;
}a[40011],ask[40011];

struct rec{
    int x,l,r,k,q,id;
}d[400011];

struct tree{
    int ls,rs,q;
}tr[32000001];

int ans[40011],g[40011],next[80011],y[80011],dfn[80011],size[80011];
int fa[40011][16],que[40011],num[40011],root[40011],dep[40011];
int T,tc,tot,ts,t,n,m,q,i,x,z,j,tt;

void star(int i,int j)
{
    tt++;
    next[tt]=g[i];
    g[i]=tt;
    y[tt]=j;
}

bool cmp(rec a,rec b)
{
    if(a.x==b.x)return a.k<b.k;
    else return a.x<b.x;
}

void dfs(int x)
{
    int j,k;
    size[x]=1;
    j=g[x];
    dfn[x]=++t;
    while(j!=0){
        k=y[j];
        if(k!=fa[x][0]){
            fa[k][0]=x;
            dep[k]=dep[x]+1;
            dfs(k);
            size[x]+=size[k];
        }
        j=next[j];
    }
}

int jump(int x,int z)
{
    int e;
    e=0;
    while(z){
        if(z%2==1)x=fa[x][e];
        z/=2;
        e++;
    }
    return x;
}

void newrec(int l,int r,int x,int y,int q)
{
    if(l>r||x>y)return;
    T++;
    d[T].x=l;d[T].l=x;d[T].r=y;d[T].k=0;d[T].q=q;
    T++;
    d[T].x=r;d[T].l=x;d[T].r=y;d[T].k=2;d[T].q=q;
    T++;
    d[T].x=x;d[T].l=l;d[T].r=r;d[T].k=0;d[T].q=q;
    T++;
    d[T].x=y;d[T].l=l;d[T].r=r;d[T].k=2;d[T].q=q;
}

void addrec(int x,int z,int q)
{
    int j,k;
    if(dep[x]>dep[z])swap(x,z);
    if(dfn[z]>=dfn[x]&&dfn[z]<dfn[x]+size[x]){
        k=jump(z,dep[z]-dep[x]-1);
        newrec(1,dfn[k]-1,dfn[z],dfn[z]+size[z]-1,q);
        newrec(dfn[k]+size[k],n,dfn[z],dfn[z]+size[z]-1,q);
        
    }
    else newrec(dfn[x],dfn[x]+size[x]-1,dfn[z],dfn[z]+size[z]-1,q);
}

int lowbit(int x)
{
    return x&-x;
}

void Insert(int &t,int l,int r,int x,int y)
{
    if(t==0)t=++tc;
    if(l==r){
        tr[t].q+=y;
        return;
    }
    int mid;
    mid=(l+r)/2;
    if(x<=mid)Insert(tr[t].ls,l,mid,x,y);
    if(x>mid)Insert(tr[t].rs,mid+1,r,x,y);
    tr[t].q=tr[tr[t].ls].q+tr[tr[t].rs].q;
}

void Ins(int l,int r,int y,int z)
{
    while(r){
        Insert(root[r],1,tot,y,z);
        r-=lowbit(r);
    }
    l--;
    while(l){
        Insert(root[l],1,tot,y,-z);
        l-=lowbit(l);
    }
}

int Find(int l,int r,int k)
{
    if(l==r)return num[l];
    int mid,i,chk;
    chk=0;
    mid=(l+r)/2;
    for(i=1;i<=ts;i++)chk+=tr[tr[que[i]].ls].q;
    if(chk>=k){
        for(i=1;i<=ts;i++)que[i]=tr[que[i]].ls;
        return Find(l,mid,k);
    }
    else{
        for(i=1;i<=ts;i++)que[i]=tr[que[i]].rs;
        return Find(mid+1,r,k-chk);
    }
}

int Ask(int x,int z)
{
    ts=0;
    while(x<=n){
        que[++ts]=root[x];
        x+=lowbit(x);
    }
    return Find(1,tot,z);
}

int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for(i=1;i<n;i++){
        scanf("%d%d",&x,&z);
        star(x,z);
        star(z,x);
    }
    dfs(1);
    for(i=1;i<=15;i++)
        for(j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1];
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&a[i].x,&a[i].z,&a[i].q);
        if(!H[a[i].q]){
            H[a[i].q]=1;
            num[++tot]=a[i].q;
        }
    }
    sort(num+1,num+1+tot);
    for(i=1;i<=tot;i++)H[num[i]]=i;
    for(i=1;i<=m;i++)a[i].q=H[a[i].q];
    for(i=1;i<=m;i++)addrec(a[i].x,a[i].z,a[i].q);
    for(i=1;i<=q;i++){
        scanf("%d%d%d",&ask[i].x,&ask[i].z,&ask[i].q);
        T++;
        d[T].x=dfn[ask[i].x];d[T].l=d[T].r=dfn[ask[i].z];d[T].k=1;d[T].id=i;d[T].q=ask[i].q;
    }
    sort(d+1,d+1+T,cmp);
    for(i=1;i<=T;i++){
        if(d[i].k==0)Ins(d[i].l,d[i].r,d[i].q,1);
        if(d[i].k==1)ans[d[i].id]=Ask(d[i].l,d[i].q);
        if(d[i].k==2)Ins(d[i].l,d[i].r,d[i].q,-1);
    }
    for(i=1;i<=q;i++)printf("%d\n",ans[i]);
}

 

posted on 2015-04-23 15:11  razorjxt  阅读(462)  评论(0编辑  收藏  举报