BZOJ3626LCA(树剖+线段树+LCA+差分)
来源:互联网 发布:znds网络电视论坛官网 编辑:程序博客网 时间:2024/06/05 14:42
题面
给定一棵树,有q次询问,每次询问都是l,r,p,每次询问
数据范围达到了上万,显然每次询问要么log地询问,要么O(1)询问,log级的显然是比较难处理的,于是我们想到把询问离线,发现这东西满足差分的性质,即处理出
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;typedef long long LL;#define REP(i,a,b) for(register int i = (a),i##_end_ = (b); i <= i##_end_; ++i)#define DREP(i,a,b) for(register int i = (a),i##_end_ = (b);i >= i##_end_; --i)#define mem(a,b) memset(a,b,sizeof(a));int read(){ register int flag = 1,sum = 0;char c = getchar(); while(!isdigit(c)) { if(c == '-')flag = -1; c = getchar(); } while(isdigit(c)) { sum = sum * 10 + c - '0'; c = getchar(); } return sum * flag;}const int maxn = 400000+10;const int mod = 201314;int n,m;int be[maxn],ne[maxn],to[maxn],e;void add(int x,int y){ to[++e] = y;ne[e] = be[x];be[x] = e;}int dep[maxn],size[maxn],son[maxn],fa[maxn];void dfs1(int x,int dp,int faa){ dep[x] = dp;size[x] = 1; for(int i = be[x]; i; i = ne[i]) { int v = to[i]; if(v != faa) { dfs1(v,dp+1,x);fa[v] = x; size[x] += size[v]; if(!son[x] || size[son[x]] < size[v])son[x] = v; } }}int top[maxn],tid[maxn],cnt,vis[maxn];void dfs2(int x,int tp){ vis[x] = 1;top[x] = tp;tid[x] = ++cnt; if(!son[x])return ; dfs2(son[x],tp); for(int i = be[x]; i; i = ne[i]) { int v = to[i]; if(!vis[v])dfs2(v,v); }}struct T{ int id,flag,z,p; LL ans; bool operator < (const T&u)const { return z < u.z; }}q[maxn];int num;struct node{ int l,r,ld,rd,p;}ask[maxn];LL tr[maxn<<2],tag[maxn<<2];void pushdown(int h,int l,int r){ int mid = (l + r) >> 1; tag[h<<1] += tag[h]; tag[h<<1|1] += tag[h]; (tr[h<<1] += (mid - l + 1) * tag[h])%=mod; (tr[h<<1|1] += (r - mid) * tag[h])%=mod; tag[h] = 0;}void updata(int h,int l,int r,int q,int w){ if(q <= l &&r <= w) { (tr[h] += w - q + 1)%=mod; tag[h]++;return ; } int mid = (l + r) >> 1; if(tag[h])pushdown(h,l,r); if(w <= mid)updata(h<<1,l,mid,q,w); else if(q > mid)updata(h<<1|1,mid+1,r,q,w); else updata(h<<1,l,mid,q,w),updata(h<<1|1,mid+1,r,q,w); tr[h] = tr[h<<1] + tr[h<<1|1];}LL query(int h,int l,int r,int q,int w){ if(q <= l && r <= w)return tr[h]; if(tag[h])pushdown(h,l,r); int mid = (l + r) >> 1; if(w <= mid)return query(h<<1,l,mid,q,w); else if(q > mid)return query(h<<1|1,mid+1,r,q,w); else return query(h<<1,l,mid,q,w)+query(h<<1|1,mid+1,r,q,w);}void add(int x){ int y = 0; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]])swap(x,y); updata(1,1,cnt,tid[top[x]],tid[x]); x = fa[top[x]]; } updata(1,1,cnt,tid[0],tid[x]);}void solve(int id){ int x = q[id].p,y = 0; LL res = 0; while(top[x]!=top[y]) { if(dep[top[x]] < dep[top[y]])swap(x,y); (res += query(1,1,cnt,tid[top[x]],tid[x]))%=mod; x = fa[top[x]]; } (res += query(1,1,cnt,tid[0],tid[x]))%=mod; q[id].ans = res;}int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); n = read();m = read(); REP(i,1,n-1) { int x = read(); add(x,i);add(i,x); }//slpf dfs1(0,0,-1);dfs2(0,0); //sort,prehandle query REP(i,1,m) { ask[i].l = read(),ask[i].r = read(),ask[i].p = read(); q[++num] = (T){i,0,ask[i].l-1,ask[i].p}; q[++num] = (T){i,1,ask[i].r,ask[i].p}; } sort(q+1,q+1+num); REP(i,1,num) { if(!q[i].flag)ask[q[i].id].ld = i; else ask[q[i].id].rd = i; } int ths = 1,pt = -1; for(;pt < n && ths <= num;++ths) { while(pt < q[ths].z) ++pt,add(pt); solve(ths); } REP(i,1,m) cout<<(q[ask[i].rd].ans-q[ask[i].ld].ans+mod)%mod<<endl;}
阅读全文
0 0
- BZOJ3626LCA(树剖+线段树+LCA+差分)
- [NOIP2016] 天天爱跑步 LCA 树上差分 线段树
- [NOIP2016] 天天爱跑步 (LCA+线段树(动态开点)+差分+dfs序)
- BZOJ 3307 雨天的尾巴 树上差分+lca+权值线段树合并
- HDU5044【LCA+差分】
- BZOJ3626LCA
- 【POJ3417】Network-LCA算法+树上差分
- [bzoj4326][NOIP2015] 运输计划 差分+LCA
- Noip2016 天天爱跑步【LCA】【差分】
- bzoj 4390(LCA+差分)
- POJ 1201 Intervals (差分约束系统, 贪心+线段树)
- poj1201(二分+线段树)或(差分约束系统)
- [BZOJ2877][Noi2012]魔幻棋盘 && 二维线段树+差分
- hdu 5419 线段树 or 差分前缀和
- 【NOIP2015】运输计划 差分数组+线段树+树链剖分
- [省选] [线段树] [差分数组] [BZOJ1558] [JSOI2009] 等差数列
- 线段树+差分——【模板】树状数组2
- bzoj4719 [Noip2016]天天爱跑步(树+lca+树上差分+思路题)
- Javascript中两个等于号和三个等于号的区别(==/===)
- JVM自动内存管理机制
- android中代码解析drawable的xml文件
- H.264 NALU语法结构——写的最好的一篇,非常详细
- 锚点跳转滑动效果
- BZOJ3626LCA(树剖+线段树+LCA+差分)
- trie树(字典树)实现 C++
- [JSOI2008]最大数(栈+二分||动态加点的线段树)
- MyBatis解决Java实体类和表字段不一致方法
- strcmp函数的实现
- 作业二十六 Arbitrage
- 困难的串uva129(dfs)
- Java interface中方法和Object方法冲突
- 如何将多个excel文件合并成一个