BZOJ4012 点分治+排序
来源:互联网 发布:淘宝男鞋 编辑:程序博客网 时间:2024/05/04 10:37
点分治:
记录每个分支根到它管辖所有节点的距离和颜色,按颜色排序后求前缀和。
#include <cassert>#include <iostream>#include <cstdio>#include <vector>#include <algorithm> #define zw for (int i=head[u];i;i=e[i].next)#define y e[i].b#define INF 2147483647#define N 150050 using namespace std; typedef long long LL; struct Edge{ int a,b,v,next; }e[2*N]; struct data{ int c;LL L;}identity;vector<data> F[N][5];bool operator < (data p1,data p2) { return p1.c < p2.c; }; struct Monster{ int v; LL L; };vector<Monster> dis[N];bool operator < (Monster p1,Monster p2) { return p1.v < p2.v; }; int head[N],cnt,n,Q,A;bool vis[N];int c[N],w[N],siz[N],u,a,b,L,R,sum,rt;int bl1[N],bl2[N];LL ans = 0LL; void add(int a,int b,int v) { e[++cnt].a = a; e[cnt].b = b; e[cnt].v = v; e[cnt].next = head[a]; head[a] = cnt; return ;} void get_rt(int u,int fa) { w[u] = 0; siz[u] = 1; zw if (!vis[y] && y != fa) { get_rt(y,u); siz[u] += siz[y]; w[u] = max(siz[y],w[u]); } w[u] = max(sum-siz[u],w[u]); if (w[u] < w[rt]) rt = u; return ;} int get_sum(int u,int fa) { int tmp = 1; zw if (!vis[y] && y != fa) tmp += get_sum(y,u); return tmp;} void DFS(int u,int fa,int w1,int w2,int len) { bl1[u] = w1; bl2[u] = w2; zw if (y != fa && !vis[y]) { F[w1][w2].push_back( (data){ c[y] , len+e[i].v } ); dis[w1].push_back( (Monster){ y , len+e[i].v } ); DFS(y,u,w1,w2,len + e[i].v); } return ;} void solve(int u) { vis[u] = true; int son = 0; dis[u].push_back( (Monster) {u,0} ); zw if (!vis[y]) { ++son; F[u][son].push_back( (data) {0,0LL} ); F[u][son].push_back( (data) {c[y],e[i].v} ); dis[u].push_back( (Monster){y,e[i].v} ); DFS(y,u,u,son,e[i].v); sort( F[u][son].begin() , F[u][son].end() ); for (int i=1;i<F[u][son].size();i++) F[u][son][i].L += F[u][son][i-1].L; sort( dis[u].begin() , dis[u].end() ); } zw if (!vis[y]) { sum = get_sum(y,u); rt = 0; get_rt(y,y); solve(rt); }} int paul(int u,int i,int c) { int l = 0 , r = F[u][i].size() - 1; while (l < r) { int mid = (l + r + 1) / 2; int k = F[u][i][mid].c; if (F[u][i][mid].c <= c) l = mid; else r = mid - 1; } return l;} int get_dis(int u,int root) { assert(dis[u].size() > 0); int l = 0 , r = dis[u].size() - 1; while (l < r) { int mid = (l + r + 1) / 2; int k = dis[u][mid].v; if (dis[u][mid].v <= root) l = mid; else r = mid - 1; } return dis[u][l].L;} void get_ans(int u,int f,int root) { LL tmp = 0LL; LL DIS = get_dis(u,root); if (L <= c[u] && c[u] <= R) ans += DIS; for (int i=0;i<4;i++) if (bl2[f] != i && F[u][i].size()) { int p1 = paul(u,i,L-1) , p2 = paul(u,i,R); LL k = F[u][i][p2].L - F[u][i][p1].L; ans += DIS * (p2 - p1) + k; } if (bl1[u]) get_ans(bl1[u],u,root); return ;} int main(){ //freopen("4012.in","r",stdin); //freopen("4012.out","w",stdout); //assert(0); scanf("%d%d%d",&n,&Q,&A); for (int i=1;i<=n;i++) scanf("%d",&c[i]) , c[i]++; for (int i=1;i<=n-1;i++) { int a,b,v; scanf("%d%d%d",&a,&b,&v); add(a,b,v); add(b,a,v); } sum = n; w[0] = INF; rt = 0; get_rt(1,1); solve(rt); bl2[0] = 5; while (Q--) { scanf("%d%d%d",&u,&a,&b); L = (a + ans) % A; L++; R = (b + ans) % A; R++; if (L > R) swap(L,R); ans = 0LL; get_ans(u,0,u); #ifdef ONLINE_JUDGE printf("%lld\n",ans); #else printf("%I64d\n",ans); #endif } //fclose(stdin);fclose(stdout); return 0;}
0 0
- BZOJ4012 点分治+排序
- BZOJ4012【动态点分治】
- bzoj4012开店 动态点分治
- [BZOJ4012]开店 点分治+STL
- bzoj4012(动态点分治+卡常数)
- BZOJ4012【拓扑排序】
- [动态树分治] BZOJ4012 [HNOI2015]开店
- 树分治-点分治
- 点分治
- 点分治
- 点分治
- 点分治
- 点分治
- 点分治。。。。。
- 点分治
- 点分治
- 点分治
- 点分治
- 统计学习-基本术语和概念
- linux rpm方式 安装 jdk1.7
- SVD的计算方法
- 【同步、异步、阻塞、非阻塞】的区别
- iOS中16进制转nsdata
- BZOJ4012 点分治+排序
- tomcat nginx默许的post大小限制
- 欢迎使用CSDN-markdown编辑器
- 数组排序
- 重构-改善既有的代码设计(一)
- java实现http post请求
- 69 column window is too narrow
- sqlserver中cast,convert,datepart,left,right这三个函数的使用讲解
- 选择排序