• 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
    ",ans[i]);
    }
  • 相关阅读:
    C#注意事项
    组件化开发
    kettle导数删除并插入更新数据_20161130
    MySQL_各城市在线产品天订单数据20161130
    MySQL_杭州11月1-29号在线产品在线天数、销售天数_20161129
    kettle每天自动发送邮件总结_20161128
    MYSQL_与excel结合在excel中用&连接符快速创建表头_20161125
    MySQL_杭州拱墅区、西湖区近9-11月销售过的产品_20161125
    MySQL_产品昨日库存与历史入库历史出库成本_20161124
    MySQL11月16-11月21日活动赠送的优惠券使用率_20161124
  • 原文地址:https://www.cnblogs.com/applejxt/p/4450625.html
Copyright © 2020-2023  润新知