码迷,mamicode.com
首页 > 编程语言 > 详细

CF293E Close Vertices 点分治+树状数组

时间:2019-09-07 01:35:07      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:else   --   size   while   fine   alc   add   lse   length   

开始zz写了一个主席树,后来发现写个树状数组就行~

#include <cstdio>  
#include <vector>   
#include <algorithm>    
#include <bits/stdc++.h> 
#define N 100005   
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int length,weight;    
namespace BIT
{ 
    int C[N];
    int lowbit(int t) 
    {
        return t&(-t); 
    }
    void update(int x,int v) 
    {
        for(;x<N;x+=lowbit(x)) C[x]+=v;
    }
    int query(int x)
    {
        int re=0;
        for(;x>0;x-=lowbit(x)) re+=C[x];
        return re;      
    }
}; 
ll answer; 
struct Node
{
    int u,d1,d2;  
    Node(int u=0,int d1=0,int d2=0):u(u),d1(d1),d2(d2){}   
};  
vector<Node>v;    
bool cmp(Node a,Node b) 
{
    return a.d2<b.d2;     
}
int n,edges,root,sn; 
int hd[N],to[N<<1],nex[N<<1],val[N<<1];   
int size[N],mx[N],vis[N],rt[N]; 
void add(int u,int v,int c) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; 
} 
void getroot(int u,int ff)
{
    size[u]=1,mx[u]=0; 
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]]) 
            getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
    mx[u]=max(mx[u],sn-size[u]); 
    if(mx[u]<mx[root]) root=u; 
}   
// d1<=l d2<=w
void getdis(int u,int ff,int d1,int d2) 
{  
    v.push_back(Node(u,d1,d2));  
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]]) 
            getdis(to[i],u,d1+1,d2+val[i]);    
}
ll calc(int u,int D1,int D2) 
{    
    getdis(u,0,D1,D2);      
    sort(v.begin(),v.end(),cmp); 
    ll re=0; 
    int i,j,l=0,r=(int)v.size()-1;   
    for(i=1;i<(int)v.size();++i) BIT::update(v[i].d1+1,1);
    while(l<r) 
    {
        if(v[l].d2+v[r].d2<=weight) 
        {
            re+=(ll)BIT::query(length-v[l].d1+1); 
            ++l,BIT::update(v[l].d1+1,-1); 
        }
        else 
        {
            BIT::update(v[r].d1+1,-1); 
            --r;       
        }
    } 
    v.clear();  
    return re; 
}
void solve(int u) 
{ 
    vis[u]=1; 
    answer+=calc(u,0,0);     
    for(int i=hd[u];i;i=nex[i]) if(!vis[to[i]]) answer-=calc(to[i],1,val[i]);            
    for(int i=hd[u];i;i=nex[i]) 
        if(!vis[to[i]]) 
            sn=size[to[i]],root=0,getroot(to[i],u),solve(root);    
}
int main() 
{
    int i,j; 
    // setIO("input");  
    scanf("%d%d%d",&n,&length,&weight);  
    for(i=1;i<n;++i) 
    {
        int a=i+1,b,c; 
        scanf("%d%d",&b,&c),add(a,b,c),add(b,a,c);       
    }    
    mx[root=0]=sn=n,getroot(1,0),solve(root);   
    printf("%lld\n",answer);    
    return 0;    
}

  

CF293E Close Vertices 点分治+树状数组

标签:else   --   size   while   fine   alc   add   lse   length   

原文地址:https://www.cnblogs.com/guangheli/p/11478963.html

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