• [loj2116]「HNOI2015」开店 动态点分治


    4012: [HNOI2015]开店

    Time Limit: 70 Sec  Memory Limit: 512 MB
    Submit: 2452  Solved: 1089
    [Submit][Status][Discuss]

    Description

     风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到

    人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的
    想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面
    向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n
    个地方,编号为 1 到 n,被 n-1 条带权的边连接起来。每个地方都住着一个妖怪,
    其中第 i 个地方的妖怪年龄是 x_i。妖怪都是些比较喜欢安静的家伙,所以它们并
    不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 3。妖怪和人一
    样,兴趣点随着年龄的变化自然就会变化,比如我们的 18 岁少女幽香和八云紫就
    比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以
    幽香打算选择一个地方 u(u为编号),然后在 u开一家面向年龄在 L到R 之间(即
    年龄大于等于 L、小于等于 R)的妖怪的店。也有可能 u这个地方离这些妖怪比较
    远,于是幽香就想要知道所有年龄在 L 到 R 之间的妖怪,到点 u 的距离的和是多
    少(妖怪到 u 的距离是该妖怪所在地方到 u 的路径上的边的权之和) ,幽香把这个
    称为这个开店方案的方便值。幽香她们还没有决定要把店开在哪里,八云紫倒是准
    备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。
     

    Input

     第一行三个用空格分开的数 n、Q和A,表示树的大小、开店的方案个数和妖

    怪的年龄上限。 
    第二行n个用空格分开的数 x_1、x_2、…、x_n,x_i 表示第i 个地点妖怪的年
    龄,满足0<=x_i<A。(年龄是可以为 0的,例如刚出生的妖怪的年龄为 0。) 
    接下来 n-1 行,每行三个用空格分开的数 a、b、c,表示树上的顶点 a 和 b 之
    间有一条权为c(1 <= c <= 1000)的边,a和b 是顶点编号。 
    接下来Q行,每行三个用空格分开的数 u、 a、 b。对于这 Q行的每一行,用 a、
    b、A计算出 L和R,表示询问“在地方 u开店,面向妖怪的年龄区间为[L,R]的方
    案的方便值是多少”。对于其中第 1 行,L 和 R 的计算方法为:L=min(a%A,b%A), 
    R=max(a%A,b%A)。对于第 2到第 Q行,假设前一行得到的方便值为 ans,那么当
    前行的 L 和 R 计算方法为: L=min((a+ans)%A,(b+ans)%A), 
    R=max((a+ans)%A,(b+ans)%A)。 
     

    Output

    对于每个方案,输出一行表示方便值。 

     

    Sample Input

    10 10 10
    0 0 7 2 1 4 7 7 7 9
    1 2 270
    2 3 217
    1 4 326
    2 5 361
    4 6 116
    3 7 38
    1 8 800
    6 9 210
    7 10 278
    8 9 8
    2 8 0
    9 3 1
    8 0 8
    4 2 7
    9 7 3
    4 7 0
    2 2 7
    3 2 1
    2 3 4

    Sample Output

    1603
    957
    7161
    9466
    3232
    5223
    1879
    1669
    1282
    0

    HINT

     满足 n<=150000,Q<=200000。对于所有数据,满足 A<=10^9

     
    可以说比较裸了
      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<cstdio>
      6 #include<algorithm>
      7 #include<vector>
      8 #define ll long long
      9 #define maxn 300005
     10 using namespace std;
     11 inline int read() {
     12     int x=0,f=1;char ch=getchar();
     13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
     14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
     15     return x*f;
     16 }
     17 ll n,Q,A;
     18 ll a[maxn];
     19 struct Edge {
     20     int nxt[maxn],head[maxn],cnt,to[maxn],w[maxn];
     21     Edge() {memset(head,-1,sizeof(head));}
     22     void add(int u,int v,int W) {nxt[cnt]=head[u];to[cnt]=v;w[cnt]=W;head[u]=cnt++;}
     23 }e1;
     24 ll rt=0,sz[maxn],f[maxn],vis[maxn],sum,fa[maxn][21];
     25 ll dis[maxn][21],dep[maxn];
     26 int up[maxn];
     27 void dfs(int x,int pre) {
     28     for(int i=1;i<=20;i++) {
     29         if((1<<i)>=dep[x]) break; 
     30         fa[x][i]=fa[fa[x][i-1]][i-1];
     31         dis[x][i]=dis[fa[x][i-1]][i-1]+dis[x][i-1];
     32     }
     33     for(int i=e1.head[x];i>=0;i=e1.nxt[i]) {
     34         int to=e1.to[i];if(to==pre) continue;
     35         fa[to][0]=x;dis[to][0]=e1.w[i];
     36         dep[to]=dep[x]+1;dfs(to,x);
     37     }
     38 }
     39 int getdis(int x,int y) {
     40     if(!x||!y) return 0;
     41     if(dep[x]<dep[y]) swap(x,y);
     42     int t=dep[x]-dep[y];ll d=0;
     43     for(int i=20;i>=0;i--) if(t&(1<<i)) d+=dis[x][i],x=fa[x][i];
     44     for(int i=20;i>=0;i--) {
     45         if(fa[x][i]!=fa[y][i]) {
     46             d+=dis[x][i]+dis[y][i];
     47             x=fa[x][i],y=fa[y][i];
     48         }
     49     }
     50     
     51     if(y!=x) d+=dis[x][0]+dis[y][0];
     52     return d;
     53 }
     54 void findrt(int x,int pre) {
     55     sz[x]=f[x]=1;
     56     for(int i=e1.head[x];i>=0;i=e1.nxt[i]) {
     57         int to=e1.to[i];if(to==pre||vis[to]) continue;
     58         findrt(to,x);sz[x]+=sz[to];
     59         f[x]=max(f[x],sz[to]);
     60     }
     61     f[x]=max(f[x],sum-sz[x]);if(f[rt]>f[x]) rt=x;
     62     return ;
     63 }
     64 struct Node {
     65     ll val,sum,sumf,cnt;
     66     bool operator <(const Node tmp) const {return val<tmp.val;}
     67 };
     68 vector<Node> sta[maxn];
     69 void dfs1(int x,int pre,int root) {
     70     sta[root].push_back((Node){a[x],getdis(x,root),(up[root]?getdis(x,up[root]):0),1});
     71     for(int i=e1.head[x];i>=0;i=e1.nxt[i]) {
     72         int to=e1.to[i];if(to==pre||vis[to]) continue;
     73         dfs1(to,x,root);
     74     }
     75 }
     76 void build(int x) {
     77     vis[x]=1;dfs1(x,0,x);
     78     sta[x].push_back((Node){-1,0,0,0});
     79     sort(sta[x].begin(),sta[x].end());
     80     int SZ=sta[x].size();
     81     for(int i=1;i<SZ;i++) {
     82         sta[x][i].sum+=sta[x][i-1].sum;
     83         sta[x][i].sumf+=sta[x][i-1].sumf;
     84         sta[x][i].cnt+=sta[x][i-1].cnt;
     85     }
     86     for(int i=e1.head[x];i>=0;i=e1.nxt[i]) {
     87         int to=e1.to[i];if(vis[to]) continue;
     88         sum=sz[to];rt=0;findrt(to,0);
     89         up[rt]=x;build(rt);
     90     }
     91 }
     92 ll lastans=0;
     93 ll query(int u,int L,int R) {
     94     //cout<<u<<' '<<L<<' '<<R<<':'<<endl;
     95     ll ans=0,cans=0;
     96     for(int i=u;i;i=up[i]) {
     97         int l=0,r=sta[i].size()-1;
     98         while(l<=r) {
     99             int mid=l+r>>1;
    100             if(sta[i][mid].val<=R) l=mid+1;
    101             else r=mid-1;
    102         }
    103         int ed=l-1;
    104         l=0,r=sta[i].size()-1;
    105         while(l<=r) {
    106             int mid=l+r>>1;
    107             if(sta[i][mid].val<=L-1) l=mid+1;
    108             else r=mid-1;
    109         }
    110         int st=l-1;
    111         ans+=(sta[i][ed].sum-sta[i][st].sum);
    112         if(i!=u) ans+=(sta[i][ed].cnt-sta[i][st].cnt)*getdis(i,u);
    113         if(up[i]) ans-=(sta[i][ed].sumf-sta[i][st].sumf)+(sta[i][ed].cnt-sta[i][st].cnt)*getdis(u,up[i]);
    114     }
    115     return ans;
    116 }
    117 int main() {
    118     n=read(),Q=read(),A=read();
    119     for(int i=1;i<=n;i++) a[i]=read();
    120     for(int i=1;i<n;i++) {
    121         int u=read(),v=read(),w=read();
    122         e1.add(u,v,w);e1.add(v,u,w);
    123     }
    124     dep[1]=1;dfs(1,0);//cout<<getdis(2,8)<<endl;
    125     sum=n;sz[0]=f[0]=2147483647;
    126     findrt(1,0);build(rt);
    127     while(Q--) {
    128         int u=read(),aa=read(),bb=read();
    129         int L=min((aa+lastans)%A,(bb+lastans)%A),R=max((aa+lastans)%A,(bb+lastans)%A);
    130         lastans=query(u,L,R);
    131         printf("%lld
    ",lastans);
    132     }
    133 }
    View Code
  • 相关阅读:
    1.3 Starting a New Job 1.3.3 Background Reading(I)
    1.3 Starting a New Job 1.3.1 Preparation
    1.2 Interview 1.2.4 Sample Test(IV)
    1.2 Interview 1.2.4 Sample Test(III)
    Jquery获取元素集合并遍历
    Oracle21c RAC+DG生产项目实战(RHEL8+Oracle集群+容灾+CDB/PDB)
    Django
    Linux 实用命令
    Python人工智能:原理、实践及应用-资料分享
    关于HDFS的NameNode和SecondaryNameNode的一些疑问解答
  • 原文地址:https://www.cnblogs.com/wls001/p/10191766.html
Copyright © 2020-2023  润新知