bzoj4012[HNOI2015]开店

http://www.lydsy.com/JudgeOnline/problem.php?id=4012

动态树分治。

做过上一题捉迷藏,对动态树分治有了更深的认识。

”所有顶点的度数都小于或等于3“,好强的暗示。

类似的做法,先求重心,对于与重心相连的每棵子树,求出到每棵子树中所有点到重心的距离。每棵子树中的点按年龄排序,并求距离的前缀和。

然后递归即可。

对于询问,因为每个点最多“属于”$logn$个重心,在这$logn$个重心所对应的树中二分即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b)  for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxn=150000;

int n,Q,A;
int age[maxn+100];
int now[2],info[2][maxn+100];
struct Tedge{int v,cost,next,kind;}edge[2][maxn*20];

void addedge(int k,int u,int v,int cost,int kind=0)
  {
      edge[k][++now[k]]=k?(Tedge){v,cost,info[k][u],kind}:(Tedge){v,cost,info[k][u],0};
      info[k][u]=now[k];
  }

struct Tdata
  {
      int age,dist;LL sum;
      Tdata(int _age=0,int _dist=0){age=_age;dist=_dist;sum=0;}
      friend bool const operator <(const Tdata a,const Tdata b){return a.age<b.age;}
  };

int num;
int mark[maxn+100],gen[maxn+100],degree[maxn+100];
vector<Tdata> S[maxn+100][4];

int sz[maxn+100],mx[maxn+100];
void getrt(int u,int fa,int all,int &rt)
  {
      int i,v;
      sz[u]=1;mx[u]=0;
      for(i=info[0][u],v=edge[0][i].v;i!=-1;i=edge[0][i].next,v=edge[0][i].v)if(!mark[v] && v!=fa)getrt(v,u,all,rt),sz[u]+=sz[v],upmax(mx[u],sz[v]);
      upmax(mx[u],all-sz[u]);
      if(!rt || mx[u]<mx[rt])rt=u;
  }
void dfs(int u,int fa,int dist,int cur,int kind)
  {
      S[cur][kind].p_b(Tdata(age[u],dist));
      addedge(1,u,cur,dist,kind);
      int i,v,cost;
      for(i=info[0][u],v=edge[0][i].v,cost=edge[0][i].cost;i!=-1;i=edge[0][i].next,v=edge[0][i].v,cost=edge[0][i].cost)if(!mark[v] && v!=fa)dfs(v,u,dist+cost,cur,kind);
  }
void prep(int u,int all)
  {
      if(all<=1)return;
      int i,j,rt=0,tmp=0;
      getrt(u,-1,all,rt);
      getrt(rt,-1,all,tmp);
      int cur=++num,v,cost;
        mark[rt]=cur;gen[cur]=rt;degree[cur]=0;
        addedge(1,rt,cur,0,0);
      for(i=info[0][rt],v=edge[0][i].v,cost=edge[0][i].cost;i!=-1;i=edge[0][i].next,v=edge[0][i].v,cost=edge[0][i].cost)if(!mark[v])
        {
            int t=++degree[cur];
          dfs(v,rt,cost,cur,t);
          sort(S[cur][t].begin(),S[cur][t].end());
          S[cur][t][0].sum=S[cur][t][0].dist;re(j,1,int(S[cur][t].size())-1)S[cur][t][j].sum=S[cur][t][j-1].sum+S[cur][t][j].dist;
          prep(v,sz[v]);
        }
  }
LL ask(int x,int M)
  {
      int i,j,cur,dis,kind;LL res=0;
      for(i=info[1][x],cur=edge[1][i].v,dis=edge[1][i].cost,kind=edge[1][i].kind;i!=-1;i=edge[1][i].next,cur=edge[1][i].v,dis=edge[1][i].cost,kind=edge[1][i].kind)
        {
            if(age[gen[cur]]<=M)res+=dis;
          re(j,1,degree[cur])if(j!=kind)
            {
                vector<Tdata>::iterator it=upper_bound(S[cur][j].begin(),S[cur][j].end(),Tdata(M));
                if(it==S[cur][j].begin())continue;
                it--;
                res+=it->sum+1LL*(it-S[cur][j].begin()+1)*dis;
            }
        }
      return res;
  }
              
int main()
  {
      freopen("bzoj4012.in","r",stdin);
      freopen("bzoj4012.out","w",stdout);
      int i;
      n=gint();Q=gint();A=gint();
      re(i,1,n)age[i]=gint();
      mmst(now,-1);mmst(info,-1);
      re(i,1,n-1){int u=gint(),v=gint(),cost=gint();addedge(0,u,v,cost);addedge(0,v,u,cost);}
      prep(1,n);
      LL lastans=0;
      while(Q--)
        {
            int x=gint(),a=gint(),b=gint(),L=(LL(a)+lastans)%LL(A),R=(LL(b)+lastans)%LL(A);
            if(L>R)swap(L,R);
            lastans=ask(x,R)-ask(x,L-1);
            PF("%I64d\n",lastans);
        }
      return 0;
  }
View Code

 

posted @ 2015-11-23 21:27  maijing  阅读(440)  评论(0编辑  收藏  举报