BZOJ4012 [HNOI2015]开店
Description
风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到
Input
第一行三个用空格分开的数 n、Q和A,表示树的大小、开店的方案个数和妖
Output
对于每个方案,输出一行表示方便值。
Sample Input
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
957
7161
9466
3232
5223
1879
1669
1282
0
HINT
满足 n<=150000,Q<=200000。对于所有数据,满足 A<=10^9
写完莫名其妙地过了样例,交上去莫名其妙地WA了一发后改了改范围然后莫名其妙地A了。
考虑用动态树分治来做。对于以x为分治根的所有节点,记录它子树中所有点到它本身的颜色和距离,以及它子树中所有点到它分治父亲的颜色和距离。sort一下预处理前缀和,就可以在上面二分了,为了省事加了个虚拟节点颜色为-1。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
char ch=getchar();int x=,f=;
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
const int maxn=;
typedef long long LL;
int n,q,first[maxn],next[maxn],to[maxn],dis[maxn],e;
void AddEdge(int w,int v,int u) {
to[++e]=v;dis[e]=w;next[e]=first[u];first[u]=e;
to[++e]=u;dis[e]=w;next[e]=first[v];first[v]=e;
}
int mn[maxn][],dep[maxn],pos[maxn],cnt;
void dfs(int x,int fa) {
mn[++cnt][]=dep[x];pos[x]=cnt;
ren if(to[i]!=fa) {
dep[to[i]]=dep[x]+dis[i];
dfs(to[i],x);
mn[++cnt][]=dep[x];
}
}
int Log[maxn];
void init() {
Log[]=-;rep(,cnt) Log[i]=Log[i>>]+;
for(int j=;(<<j)<=cnt;j++)
for(int i=;i+(<<j)-<=cnt;i++)
mn[i][j]=min(mn[i][j-],mn[i+(<<j-)][j-]);
}
LL dist(int x,int y) {
LL ans=dep[x]+dep[y];x=pos[x];y=pos[y];if(x>y) swap(x,y);
int k=Log[y-x+];
return ans-2LL*min(mn[x][k],mn[y-(<<k)+][k]);
}
int age[maxn],vis[maxn],f[maxn],s[maxn],size,root;
void getroot(int x,int fa) {
s[x]=;int maxs=;
ren if(!vis[to[i]]&&to[i]!=fa) getroot(to[i],x),s[x]+=s[to[i]],maxs=max(maxs,s[to[i]]);
f[x]=max(maxs,size-s[x]);
if(f[root]>f[x]) root=x;
}
struct Arr {
int c;LL val;
bool operator < (const Arr& ths) const {return c<ths.c;}
Arr operator - (const Arr& ths) const {Arr t;t.val=val-ths.val;t.c=c-ths.c;return t;}
}A[maxn*];
int cur,L1[maxn],R1[maxn],L2[maxn],R2[maxn];
void dfs(int x,int fa,int dep) {
A[++cur]=(Arr){age[x],dep};s[x]=;
ren if(to[i]!=fa&&!vis[to[i]]) dfs(to[i],x,dep+dis[i]),s[x]+=s[to[i]];
}
int fa[maxn];
void solve(int x,int F) {
vis[x]=;fa[x]=F;
A[++cur]=(Arr){-,};L1[x]=cur;dfs(x,,);R1[x]=cur;
sort(A+L1[x],A+R1[x]+);
rep(L1[x]+,R1[x]) A[i].val+=A[i-].val;
ren if(!vis[to[i]]) {
size=f[]=s[to[i]];getroot(to[i],root=);
A[++cur]=(Arr){-,};L2[root]=cur;dfs(to[i],,dis[i]);R2[root]=cur;
sort(A+L2[root],A+R2[root]+);
rep(L2[root]+,R2[root]) A[i].val+=A[i-].val;
solve(root,x);
}
}
LL lastans,T;
Arr get(int x,int ql,int qr,int L,int R) {
Arr t;
t.c=qr;
int pos1=upper_bound(A+L,A+R+,t)-A-;
t.c=ql-;
int pos2=upper_bound(A+L,A+R+,t)-A-;
t.c=pos1-pos2;t.val=A[pos1].val-A[pos2].val;
return t;
}
LL query(int x,int l,int r) {
LL ret=get(x,l,r,L1[x],R1[x]).val;
for(int i=x;fa[i];i=fa[i]) {
Arr t=get(fa[i],l,r,L1[fa[i]],R1[fa[i]])-get(i,l,r,L2[i],R2[i]);
ret+=t.val+t.c*dist(fa[i],x);
}
return ret;
}
int main() {
n=read();q=read();T=read();
rep(,n) age[i]=read();
rep(,n) AddEdge(read(),read(),read());
dfs(,);init();
size=f[]=n;getroot(,root=);
int t=root;solve(root,);root=t;
while(q--) {
int u=read(),a=(read()+lastans)%T,b=(read()+lastans)%T;
if(a>b) swap(a,b);
printf("%lld\n",lastans=query(u,a,b));
}
return ;
}
BZOJ4012 [HNOI2015]开店的更多相关文章
- [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)
4012: [HNOI2015]开店 Time Limit: 70 Sec Memory Limit: 512 MBSubmit: 2168 Solved: 947[Submit][Status] ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- BZOJ4012 HNOI2015开店(树链剖分+主席树)
考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑:询问某点到所有黑点的距离之和. 注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2.要求 ...
- BZOJ4012: [HNOI2015]开店【动态点分治】
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ4012 [HNOI2015]开店 (动态点分治)
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ4012 [HNOI2015]开店 【动态点分治 + splay】
题目链接 BZOJ4012 题解 Mychael并没有A掉,而是T掉了 讲讲主要思路 在点分树上每个点开两棵\(splay\), 平衡树\(A\)维护子树中各年龄到根的距离 平衡树\(B\)维护子树中 ...
- 【BZOJ4012】[HNOI2015]开店 动态树分治+二分
[BZOJ4012][HNOI2015]开店 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点 ...
- 【BZOJ4012】开店(主席树)
[BZOJ4012]开店(主席树) 题面 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱 ...
- [HNOI2015]开店 树链剖分,主席树
[HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...
随机推荐
- HM必修1
高中数学必修一 笔记与拓展 1. 集合与函数概念 集合概念 集合是一个基本的数学概念. 集合是由集合的元素构成的. 当且仅当两个集合中包含着完全相同的元素且都不包含其它元素时两个集合相等. 集合是确定 ...
- Windows命令行重命名文件
RENAME D:\Cache\xyz.html xyz%date:~0,4%%date:~5,2%%date:~8,2%.tar.gz
- XShell上传下载命令
参考:https://www.centos.bz/2012/12/xshell-securecrtrz-sz-upload-download/ 上传文件时,执行rz就会弹出文件选择对话框来选择文件.下 ...
- hdu 1425 sort 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1425 常规的方法是对输入的数从大到小进行排序(可以用sort或qsort),然后输出前m大的数. 不过 ...
- 【python】继承时注意事项
1. __init__ 注意事项 如果父类有__init__函数,子类没有,则子类自动调用父类__init__函数 如果父类有__init__函数,子类也有,则子类必须主动调用父类__init__函数 ...
- 【数据结构】hanoi
#include<stdio.h> void hanoi(int n,char x,char y,char z) { ; ) printf("%d. Move disk %d f ...
- CSS鼠标样式整理
鼠标样式的标签: cursor:*; //该属性定义了鼠标指针放在一个元素边界范围内时所用的光标形状: 鼠标样式: 值 描述 url 需使用的自定义光标的 URL. 注释:请在此列表的末端始终定义一 ...
- 国密SM4对称算法实现说明(原SMS4无线局域网算法标准)
国密SM4对称算法实现说明(原SMS4无线局域网算法标准) SM4分组密码算法,原名SMS4,国家密码管理局于2012年3月21日发布:http://www.oscca.gov.cn/News/201 ...
- setup 桌面化设置网卡
# setup
- .net学习笔记---HttpRuntime类
HttpRuntime在ASP.NET处理请求中负责的是创建HttpContext对象以及调用HttpApplicationFactory创建HttpApplication. 其定义如下: publi ...