zoukankan      html  css  js  c++  java
  • codeforces 293E 树上点分治+bit维护二维偏序

    https://codeforc.es/contest/293/problem/E

    题解:

    如果我们和poj1741一样,暴力预处理出子树中所有的点对信息

    那么问题就变成了一个二维偏序问题

    多少个点对满足w1+w2<=W且l1+l2<=L

    参考树状数组求逆序对,用树状数组保存l1的信息,对于每个l2,查询前缀和,然后删除自身

    注意细节

    #include<bits/stdc++.h>
    #define endl '
    '
    #define ll long long
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pii pair<ll,int>
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false)
    #define show(x) cout<<#x<<"="<<x<<endl
    #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
    #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
    #define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    #define forn(i,x) for(int i=head[x];i;i=e[i].next)
    using namespace std;
    const int maxn=1e5+10,maxm=2e5+10;
    const int INF=0x3f3f3f3f;
    const int mod=1e9+7;
    const double PI=acos(-1.0);
    int casn,n,m;
    ll k;
    struct bit{
        ll node[maxn];
        inline int lb(int x) {return x&(-x);}
        inline void update(int pos,ll val=1){
            pos++;if(pos<=0) return ;
            for(int i=pos;i&&i<=n;i+=lb(i))node[i]+=val;
        }
        inline ll ask(int pos){
            ll sum=0;pos++;if(pos<=0) return 0;
            for(int i=pos;i>0;i-=lb(i))sum+=node[i];return sum;
        }
        inline ll query(int l,int r){return ask(r)-ask(l-1);}
    }tree;
    class graph{public:
      struct node{int to,next;ll cost;}e[maxm];
      int head[maxn],nume,n,sz[maxn],maxt,stree[maxn];
      void add(int a,int b,ll c=0){e[++nume]={b,head[a],c};head[a]=nume;}
      int vis[maxn],num[maxn],all,mid;
      void getmid(int now=1,int pre=0){
        sz[now]=1;
        for(int i=head[now];i;i=e[i].next){
          if(e[i].to==pre||vis[e[i].to]) continue;
          getmid(e[i].to,now);
          sz[now]+=sz[e[i].to];
        }
        int tmp=max(sz[now]-1,all-sz[now]);
        if(maxt>tmp) maxt=tmp,mid=now;
      }//base
      pii dis[maxn];
      int dfn,mxd;
      ll ans;
      void init(int n){
        this->n=n,nume=1,mid=0;
        rep(i,1,n) vis[i]=head[i]=0;
      }
      ll getdis(int now,int pre,int d,ll s){
        dis[++dfn]={s,d};mxd=max(mxd,d);
        for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
          if(to==pre||vis[to]) continue;
          getdis(to,now,d+1,s+e[i].cost);
        }
      }
      ll getans(int now,int d=0,ll s=0){
        dfn=0;mxd=0;
        getdis(now,0,d,s);
        sort(dis+1,dis+1+dfn);
        ll ans=0;
        int l=1,r=dfn;
        while(l<r&&dis[l].fi+dis[r].fi>k)r--;
        rep(i,l+1,r) tree.update(dis[i].se);
        while(l<r){
            if(dis[l].fi+dis[r].fi<=k) {
                ans+=tree.ask(min(m-dis[l].se,mxd));
                tree.update(dis[++l].se,-1);
            }else tree.update(dis[r--].se,-1);
        }
        return ans;
      }
      void divide(int now){
        vis[now]=1;ans+=getans(now);
        for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
          if(vis[to]) continue;
          ans-=getans(to,1,e[i].cost);
          all=sz[to],maxt=n+1;
          getmid(to,now);divide(mid);
        }
      }
      void solve(){
        ans=0;maxt=all=n;
        getmid();divide(mid);
      }
    }g;
    
    int main() {IO;
      cin>>n>>m>>k;
      g.init(n);
      rep(i,2,n){
        int a;ll c;cin>>a>>c;
        g.add(i,a,c);g.add(a,i,c);
      }
      g.solve();
      cout<<g.ans<<endl;
    }
    
  • 相关阅读:
    Codeforces 1255B Fridge Lockers
    Codeforces 1255A Changing Volume
    Codeforces 1255A Changing Volume
    leetcode 112. 路径总和
    leetcode 129. 求根到叶子节点数字之和
    leetcode 404. 左叶子之和
    leetcode 104. 二叉树的最大深度
    leetcode 235. 二叉搜索树的最近公共祖先
    450. Delete Node in a BST
    树的c++实现--建立一棵树
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10910036.html
Copyright © 2011-2022 走看看