4012: [HNOI2015]开店
来源:互联网 发布:高中生搭配衣服知乎 编辑:程序博客网 时间:2024/04/29 02:11
4012: [HNOI2015]开店
Time Limit: 70 Sec Memory Limit: 512 MBSubmit: 1241 Solved: 536
[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
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
957
7161
9466
3232
5223
1879
1669
1282
0
HINT
满足 n<=150000,Q<=200000。对于所有数据,满足 A<=10^9
Source
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std; const int maxn = 1E5 + 5E4 + 10;typedef long long LL; struct E{ int to,w; E(){} E(int to,int w): to(to),w(w){}}; struct data{ int Num,sm; LL sum; data(){} data(int Num,LL sum,int sm): Num(Num),sum(sum),sm(sm){} bool operator < (const data &B) const {return Num < B.Num;} bool operator == (const data &B) const {return Num == B.Num;}}; int n,m,O,cnt,rt,tp,cur,Cur,Max,a[maxn],A[maxn],siz[maxn],stk[maxn];bool Huge[maxn];LL LastAns,Age; vector <E> v[maxn];vector <data> C[maxn],D[maxn];vector <int> g[maxn],Num[maxn],Dep[maxn],h[maxn]; int Lower_Bound(const vector <data> &V,int l,int r,const data &k){ while (r - l > 1) { int mid = (l + r) >> 1; if (V[mid] == k) return mid; if (k < V[mid]) r = mid; else l = mid; } if (k < V[l] || V[l] == k) return l; if (k < V[r] || V[r] == k) return r; return r + 1;} void Pre_Work(int *s,int tp,int &c){ c = 1; sort(s + 1,s + tp + 1); for (int i = 2; i <= tp; i++) if (s[i] != s[i-1]) s[++c] = s[i];} void Dfs1(int x,int from,int tot){ int ma = 0; siz[x] = 1; stk[++tp] = A[x]; for (int i = 0; i < v[x].size(); i++) { int to = v[x][i].to; if (to == from || Huge[to]) continue; Dfs1(to,x,tot); siz[x] += siz[to]; ma = max(ma,siz[to]); } ma = max(ma,tot - siz[x]); if (ma < Max) Max = ma,O = x;} void Dfs2(int x,int from){ stk[++tp] = A[x]; for (int i = 0; i < v[x].size(); i++) { int to = v[x][i].to; if (to == from || Huge[to]) continue; Dfs2(to,x); }} void Dfs3(int x,int from,int o,int y,int now,int sum,vector <data> &c,vector <data> &d){ Num[x].push_back(now); Dep[x].push_back(sum); siz[x] = 1; int pos = Lower_Bound(c,0,c.size() - 1,data(A[x],0,0)); c[pos].sum += 1LL * sum; ++c[pos].sm; pos = Lower_Bound(d,0,d.size() - 1,data(A[x],0,0)); d[pos].sum += 1LL * sum; ++d[pos].sm; for (int i = 0; i < v[x].size(); i++) { E e = v[x][i]; if (e.to == from || Huge[e.to]) continue; Dfs3(e.to,x,o,y,now,sum + e.w,c,d); siz[x] += siz[e.to]; }} int Work(int x,int tot){ Max = maxn; tp = 0; Dfs1(x,0,tot); Huge[O] = 1; int o = O,now = 0; Pre_Work(stk,tp,Cur); vector <data> &c = C[o]; for (int i = 0; i <= Cur; i++) c.push_back(data(stk[i],0,0)); for (int i = 0; i < v[o].size(); i++) { E e = v[o][i]; if (Huge[e.to]) continue; tp = 0; Dfs2(e.to,o); Pre_Work(stk,tp,Cur); ++cnt; vector <data> &d = D[cnt]; for (int j = 0; j <= Cur; j++) d.push_back(data(stk[j],0,0)); Dfs3(e.to,o,o,cnt,now++,e.w,c,d); h[o].push_back(cnt); for (int j = 1; j <= Cur; j++) d[j].sum += d[j-1].sum,d[j].sm += d[j-1].sm; g[o].push_back(Work(e.to,siz[e.to])); } for (int j = 1; j < c.size(); j++) c[j].sum += c[j-1].sum,c[j].sm += c[j-1].sm; return o;} LL Calc(const vector <data> &V,const int &k,int &P){ if (!k) {P = 0; return 0;} int pos = Lower_Bound(V,0,V.size() - 1,data(k,0,0)); if (pos == V.size() || V[pos].Num > k) --pos; P = pos; return V[pos].sum;} LL Query(int x,int y,int l,int r,int now){ if (x == y) return Calc(C[x],r,now) - Calc(C[x],l - 1,now); int Nex = h[x][Num[y][now]],p1,p2,p3,p4; LL ret = 0; ret = (Calc(C[x],r,p1) - Calc(D[Nex],r,p2)) - (Calc(C[x],l - 1,p3) - Calc(D[Nex],l - 1,p4)); ret += 1LL * Dep[y][now] * ((C[x][p1].sm - D[Nex][p2].sm) - (C[x][p3].sm - D[Nex][p4].sm)); if (l <= A[x] && A[x] <= r) ret += 1LL * Dep[y][now]; return ret + Query(g[x][Num[y][now]],y,l,r,now + 1);} int getint(){ char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar(); return ret;} char s[20];void Print(LL x){ if (!x) {puts("0"); return;} int len = 0; while (x) s[++len] = x % 10LL,x /= 10LL; for (int i = len; i; i--) putchar(s[i] + '0'); puts("");} int main(){ #ifdef DMC freopen("DMC.txt","r",stdin); #endif n = getint(); m = getint(); Age = getint(); for (int i = 1; i <= n; i++) a[i] = A[i] = getint(); Pre_Work(a,n,cur); for (int i = 1; i <= n; i++) A[i] = lower_bound(a + 1,a + cur + 1,A[i]) - a; for (int i = 1; i < n; i++) { int x = getint(),y,w; y = getint(); w = getint(); v[x].push_back(E(y,w)); v[y].push_back(E(x,w)); } rt = Work(1,n); while (m--) { int x = getint(),y,z; y = (getint() + LastAns) % Age; z = (getint() + LastAns) % Age; if (y > z) swap(y,z); int py = lower_bound(a + 1,a + cur + 1,y) - a; int pz = lower_bound(a + 1,a + cur + 1,z) - a; if (py > cur) {puts("0"); LastAns = 0; continue;} if (pz > cur || a[pz] > z) --pz; Print(LastAns = Query(rt,x,py,pz,0)); LastAns %= Age; } return 0;}
0 0
- BZOJ 4012: [HNOI2015]开店
- 4012: [HNOI2015]开店
- BZOJ 4012 [HNOI2015]开店
- bzoj 4012 [HNOI2015]开店 【树链剖分】
- 【HNOI2015】开店
- HNOI2015 开店
- HNOI2015开店
- 【HNOI2015】开店
- 【动态树分治】【bzoj 4012】: [HNOI2015]开店
- BZOJ 4012: [HNOI2015]开店 -- 动态树分治
- bzoj4012: [HNOI2015]开店
- bzoj4012: [HNOI2015]开店
- 【HNOI2015】开店(shop)
- [HNOI2015][JZOJ4068]开店
- BZOJ4012: [HNOI2015]开店
- BZOJ 4012 HNOI2015 开店 动态树分治+二分
- bzoj 4012: [HNOI2015]开店 (树链剖分+主席树)
- [BZOJ]4012: [HNOI2015]开店 树链剖分+主席树(线段树合并)
- 【Python学习】 之 Turtle库
- 落叶高精度表达式计算器v1.1版
- 二叉搜索树的后序遍历序列
- 仿射密码(加法密码+乘法密码)
- Hibernate进阶
- 4012: [HNOI2015]开店
- Apache 常识小札
- Codeforces Round #392 (Div. 2) D Ability To Convert
- about mvc
- Codeforces 110C Lucky Sum Of Digits 暴力
- 密钥字密码
- java学习笔记----回调的实现
- 栅栏密码
- spring入门简单实例