• COJ 0346 WZJ的旅行(二)更新动态树分治版本


    WZJ的旅行(二)
    难度级别:D; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
    试题描述

    时隔多日,WZJ又来到了幻想国旅行。幻想国由N个城市组成,由于道路翻修,只有N-1条双向道路可以通行,第i条双向道路从ui连接到vi,距离为wi。但这N-1条道路竟然连接了整个国家,每两个城市之间都有一条道路!

    WZJ知道这里景点很多,所以他想从城市s出发到城市t,旅游所有沿途的城市。WZJ想起到锻炼作用,但又不想太累,所以城市s到城市t的距离必须在L到R之间。另外WZJ规定s必须小于t,你能帮助他统计有多少对城市(s,t)符合要求吗?

    输入
    第一行为三个正整数N,L,R。
    接下来N-1行每行为三个正整数ui,vi,wi。 
    输出
    输出多少对城市(s,t)符合要求。
    输入示例
    5 3 6
    1 2 3
    2 3 3
    3 4 2
    4 5 1
    输出示例
    6
    其他说明
    城市对(1,2)、(2,3)、(1,3)、(2,4)、(2,5)、(3,5)均符合要求,共计6对
    1<=N<=100000
    1<=L<=R<=10^9
    1<=ui,vi<=N
    1<=wi<=1000

    题解:会写点分治了。。。

    首先补集转换,不在同一个子树的 = 总的 - 在同一个子树的,那么就是求路径两段在同一个子树的,dfs一遍排序再金鸡独立大法求前缀,转成区间,然后就没了。

    意会一下。。。(逃。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<cstring>
     7 #define PAU putchar(' ')
     8 #define ENT putchar('
    ')
     9 using namespace std;
    10 const int maxn=100000+10,inf=-1u>>1;
    11 struct ted{int x,y,w;ted*nxt;}adj[maxn<<1],*fch[maxn],*ms=adj;
    12 void add(int w,int y,int x){
    13     *ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
    14     *ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
    15     return;
    16 }
    17 bool vis[maxn];
    18 int L,R,CG=1,siz[maxn],f[maxn],n,size;
    19 void findcg(int x,int fa){
    20     int mxs=-inf;siz[x]=1;
    21     for(ted*e=fch[x];e;e=e->nxt){
    22         int v=e->y;if(v!=fa&&!vis[v]){
    23             findcg(v,x);siz[x]+=siz[v];
    24             mxs=max(mxs,siz[v]);
    25         }
    26     }f[x]=max(mxs,size-siz[x]);
    27     if(f[x]<f[CG])CG=x;return;
    28 }
    29 long long ans;
    30 int A[maxn],dep[maxn],cnt;
    31 void dfs(int x,int fa,int dist){
    32     A[cnt++]=dist;
    33     for(ted*e=fch[x];e;e=e->nxt){
    34         int v=e->y;if(v!=fa&&!vis[v])dfs(v,x,dist+e->w);
    35     }return;
    36 }
    37 long long cal(int x,int base){
    38     cnt=0;dfs(x,0,base);long long res=0;
    39     sort(A,A+cnt);
    40     int l=0,r=cnt-1;while(l<r)if(A[l]+A[r]>R)r--;else res+=r-l++;
    41     l=0;r=cnt-1;while(l<r)if(A[l]+A[r]>=L)r--;else res-=r-l++;
    42     return res;
    43 }
    44 void solve(int x){
    45     vis[x]=true;ans+=cal(x,0);
    46     for(ted*e=fch[x];e;e=e->nxt){
    47         int v=e->y;if(!vis[v]){
    48             ans-=cal(v,e->w);
    49             f[CG=0]=inf;size=siz[v];findcg(v,0);
    50             solve(CG);
    51         }
    52     }return;
    53 }
    54 inline int read(){
    55     int x=0,sig=1;char ch=getchar();
    56     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
    57     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
    58     return x*=sig;
    59 }
    60 inline void write(long long x){
    61     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
    62     int len=0;long long buf[15];while(x) buf[len++]=x%10,x/=10;
    63     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
    64 }
    65 void init(){
    66     n=read();L=read();R=read();
    67     for(int i=1;i<n;i++)add(read(),read(),read());
    68     f[CG=0]=inf;size=n;findcg(1,0);
    69     solve(CG);write(ans);
    70     return;
    71 }
    72 void work(){
    73     return;
    74 }
    75 void print(){
    76     return;
    77 }
    78 int main(){
    79     init();work();print();return 0;
    80 }

    当然窝萌还可以写动态树分治对不对,维护两个treap就是常数有点大耶。

    要注意一点:cal函数只需要query就行了,不需要重新计算一遍!!!

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cstring>
      7 #include<ctime>
      8 #define PAU putchar(' ')
      9 #define ENT putchar('
    ')
     10 #define CH for(int d=0;d<2;d++)if(ch[d])
     11 using namespace std;
     12 const int maxn=100000+10,maxq=200000+10,maxnode=4000000+10,maxm=200000+10,inf=-1u>>1;
     13 struct node{
     14     node*ch[2];int r,siz,v;
     15     void init(){r=rand();siz=1;ch[0]=ch[1]=NULL;return;}
     16     void update(){siz=1;CH{siz+=ch[d]->siz;}return;}
     17 }treap[maxnode],*nodecnt=treap,*cha[maxn],*tre[maxn];
     18 node*newnode(){node*x=nodecnt++;x->init();return x;}
     19 void rotate(node*&x,int d){
     20     node*k=x->ch[d^1];x->ch[d^1]=k->ch[d];k->ch[d]=x;x->update();k->update();x=k;return;
     21 }
     22 void insert(node*&x,int v){
     23     if(!x)x=newnode(),x->v=v;
     24     else{int d=v>x->v;insert(x->ch[d],v);
     25         if(x->r<x->ch[d]->r)rotate(x,d^1);else x->update();
     26     }return;
     27 }
     28 int find(node*x,int v){
     29     if(!x)return 0;
     30     if(v<=x->v)return find(x->ch[0],v);
     31     else return (x->ch[0]?x->ch[0]->siz:0)+1+find(x->ch[1],v);
     32 }
     33 struct ted{int x,y,w;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj;
     34 void add(int x,int y,int w){
     35     *ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
     36     *ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
     37     return;
     38 }
     39 int mi[maxq][20],Log[maxq],dep[maxn],pos[maxn],cnt;
     40 void build(int x,int fa,int dis){
     41     mi[++cnt][0]=dep[x]=dis;pos[x]=cnt;
     42     for(ted*e=fch[x];e;e=e->nxt){
     43         int v=e->y;if(v!=fa)build(v,x,dis+e->w),mi[++cnt][0]=dep[x];
     44     }return;
     45 }
     46 void initrmq(){
     47     Log[0]=-1;for(int i=1;i<=cnt;i++)Log[i]=Log[i>>1]+1;
     48     for(int j=1;(1<<j)<=cnt;j++)
     49         for(int i=1;i+(1<<j)-1<=cnt;i++)
     50             mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]);return;
     51 }
     52 int dist(int x,int y){
     53     int ans=dep[x]+dep[y];x=pos[x];y=pos[y];if(x>y)swap(x,y);
     54     int k=Log[y-x+1];return ans-2*min(mi[x][k],mi[y-(1<<k)+1][k]);
     55 }
     56 int CG,f[maxn],size,siz[maxn],fa[maxn];bool vis[maxn];
     57 void findcg(int x,int fa){
     58     siz[x]=1;int mxs=0;
     59     for(ted*e=fch[x];e;e=e->nxt){
     60         int v=e->y;if(v!=fa&&!vis[v]){
     61             findcg(v,x);siz[x]+=siz[v];mxs=max(mxs,siz[v]);
     62         }
     63     }f[x]=max(mxs,size-siz[x]);if(f[x]<f[CG])CG=x;return;
     64 }
     65 void dfs(int x,int fa){
     66     siz[x]=1;
     67     for(ted*e=fch[x];e;e=e->nxt){
     68         int v=e->y;if(v!=fa&&!vis[v])dfs(v,x),siz[x]+=siz[v];
     69     }return;
     70 }
     71 void solve(int x=CG){
     72     vis[x]=true;
     73     for(ted*e=fch[x];e;e=e->nxt){
     74         int v=e->y;if(!vis[v]){
     75             dfs(v,x);f[CG=0]=size=siz[v];findcg(v,x);fa[CG]=x;solve();
     76         }
     77     }return;
     78 }
     79 void update(int x){
     80     insert(tre[x],0);
     81     for(int ret=x;fa[x];x=fa[x]){
     82         int d=dist(ret,fa[x]);
     83         insert(tre[fa[x]],d);insert(cha[x],d);
     84     }return;
     85 }
     86 int k;
     87 int query(int x){
     88     int ans=find(tre[x],k);
     89     for(int ret=x;fa[x];x=fa[x]){
     90         int d=dist(ret,fa[x]);
     91         ans+=find(tre[fa[x]],k-d)-find(cha[x],k-d);
     92     }return ans;
     93 }
     94 int n,L,R;
     95 int cal(int t){
     96     k=t+1;int ans=0;for(int i=1;i<=n;i++)ans+=query(i);return ans;
     97 }
     98 inline int read(){
     99     int x=0,sig=1;char ch=getchar();
    100     while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();}
    101     while(isdigit(ch))x=10*x+ch-'0',ch=getchar();
    102     return x*=sig;
    103 }
    104 inline void write(int x){
    105     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
    106     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
    107     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
    108 }
    109 void init(){
    110     srand(time(0));
    111     n=read();L=read(),R=read();int x,y;
    112     for(int i=1;i<n;i++)x=read(),y=read(),add(x,y,read());build(1,0,0);initrmq();
    113     f[CG=0]=size=n;findcg(1,0);solve();for(int i=1;i<=n;i++)update(i);
    114     write((cal(R)-cal(L-1))>>1);
    115     return;
    116 }
    117 void work(){
    118     return;
    119 }
    120 void print(){
    121     return;
    122 }
    123 int main(){init();work();print();return 0;}
  • 相关阅读:
    【转载】怎样使用ZEMAX导出高质量的图像动画
    shell中的单引号,双引号,反引号
    docker容器以非root用户启动应用
    js操作json的基本方法
    页岩油
    shell中使用ssh
    强一致性 弱一致性 最终一致性
    CSV和excel
    workbook sheetname最大长度
    ipvs了解
  • 原文地址:https://www.cnblogs.com/chxer/p/4696951.html
Copyright © 2020-2023  润新知