• CF 293E Close Vertices——点分治


    题目:http://codeforces.com/contest/293/problem/E

    仍旧是点分治。用容斥,w的限制用排序+两个指针解决, l 的限制就用树状数组。有0的话就都+1,相对大小不变。

    切勿每次memset!!!会T得不行。add(sta[ l ].len)即可,但要判一下(l==r)以防不测。(真的有那种数据!)

    最后注意树状数组的范围是L(即L+1),不是n。不然可以尝试:

    2 10 12

    1 5

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int n,L,W,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1];
    int mn,rt,f[N],l,r,siz[N],lm;
    ll ans;
    bool vis[N];
    struct Sta{
        int w,len;Sta(int w=0,int l=0):w(w),len(l) {}
        bool operator< (const Sta &b)const
        {return w==b.w?len<b.len:w<b.w;}
    }sta[N];
    void add(int x,int y,int z)
    {
        to[++xnt]=y;nxt[xnt]=hd[x];w[xnt]=z;hd[x]=xnt;
        to[++xnt]=x;nxt[xnt]=hd[y];w[xnt]=z;hd[y]=xnt;
    }
    void getrt(int cr,int fa,int s)
    {
        siz[cr]=1;int mx=0;
        for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)
        {
            getrt(v,cr,s);siz[cr]+=siz[v];mx=max(mx,siz[v]);
        }
        mx=max(mx,s-siz[cr]);
        if(mx<mn)mn=mx,rt=cr;
    }
    void add(int x,int k){x++;for(;x<=lm;x+=(x&-x))f[x]+=k;}//x<=L+1!!!
    int query(int x){x++;int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
    void dfs(int cr,int fa,int pw,int pl)
    {
        if(pw>W||pl>L)return;
        sta[++r]=Sta(pw,pl);add(sta[r].len,1);
        for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)
            dfs(v,cr,pw+w[i],pl+1);
    }
    ll calc(int cr,int pw,int pl)
    {
        l=1;r=0;dfs(cr,0,pw,pl);
        sort(sta+l,sta+r+1);///////
    //    printf("l=%d r=%d
    ",l,r);
    //    for(int i=l;i<=r;i++)printf("sta[%d].w=%d .len=%d
    ",i,sta[i].w,sta[i].len);
        ll ret=0;
        while(l<r)
            if(sta[l].w+sta[r].w>W)add(sta[r--].len,-1);
            else ret+=query(L-sta[l].len)-(sta[l].len<=L-sta[l].len),
    //            printf("l=%d r=%d query(%d)=%d
    "
    //                ,l,r,L-sta[l].len,query(L-sta[l].len)),
                    add(sta[l++].len,-1);
        if(l==r)add(sta[l].len,-1);
    //    memset(f,0,sizeof f);///TLE!!!!!
        return ret;
    }
    void solve(int cr,int s)
    {
    //    printf("cr=%d
    ",cr);
        vis[cr]=1;ans+=calc(cr,0,0);
    //    printf("cr=%d ans=%lld
    ",cr,ans);
        for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]])
        {
            ans-=calc(v,w[i],1);
    //        printf("(cr=%d ans=%lld)(v=%d)
    ",cr,ans,v);
            int ts=(siz[cr]>siz[v]?siz[v]:s-siz[cr]);
            mn=N;getrt(v,0,ts);solve(rt,ts);
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&L,&W);lm=L+1;
        for(int i=2,y,z;i<=n;i++)
        {
            scanf("%d%d",&y,&z);add(i,y,z);
        }
        mn=N;getrt(1,0,n);solve(rt,n);
        printf("%I64d
    ",ans);
        return 0;
    }
  • 相关阅读:
    C++ string用法
    C++ 静态变量及函数的生命周期
    C++ const的用法和作用
    C++ 指针和引用的区别
    C++ struct 和 Class的区别
    C++对象模型-构造函数语意学
    大端模式与小端模式、网络字节顺序与主机字节顺序
    Spring Boot系列——Spring Boot如何启动
    分库分表利器——sharding-sphere
    并发和多线程-八面玲珑的synchronized
  • 原文地址:https://www.cnblogs.com/Narh/p/9483699.html
Copyright © 2020-2023  润新知