博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3626LCA(树剖+线段树+LCA+差分)
阅读量:6761 次
发布时间:2019-06-26

本文共 3691 字,大约阅读时间需要 12 分钟。

题面

给定一棵树,有q次询问,每次询问都是l,r,p,每次询问i=lrdeep[LCA(i,p)].

数据范围达到了上万,显然每次询问要么log地询问,要么O(1)询问,log级的显然是比较难处理的,于是我们想到把询问离线,发现这东西满足差分的性质,即处理出[1,l1][1,r]然后两者相减就是答案.想到这个之后我们考虑怎么求对于每个询问的答案.我们这么想,我们从1用一个指针往后扫,发现遇见这个点是询问中的点(l-1 or r)然后我们对这个询问的p处理下,算出答案.关键是这个答案要怎么算?这里要用到一个非常巧妙的东西,我们从1往后扫的同时,把这个点到根节点上所有点都打上+1的标记,然后我们有一个p,实际上答案就是求p到根路径上标记之和,在纸上画一下就好了.这样每次(log2n)2的复杂度,总复杂度为O(n(log2n)2).

#include
#include
#include
#include
#include
#include
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<

转载于:https://www.cnblogs.com/brodrinkwater/p/7527967.html

你可能感兴趣的文章
递归写法参考
查看>>
【Python】学习笔记八:面向对象
查看>>
单片机中PWM的原理与控制程序
查看>>
RStudio中,出现中文乱码问题的解决方案
查看>>
【SQL 触发器】
查看>>
Kafka server部署配置优化
查看>>
(转) Artificial intelligence, revealed
查看>>
【转】VS项目属性的一些配置项的总结
查看>>
Project、Target、Workspace and Scheme
查看>>
topas top vmstat
查看>>
Linux基本权限学习
查看>>
掌握jQuery插件开发
查看>>
git基本用法
查看>>
Spring Session - 使用Redis存储HttpSession例子
查看>>
如何利用框选工具获取多边形范围?
查看>>
Java读取Excel数据
查看>>
input输入框回车事件响应
查看>>
[转]win7 如何升级PowerShell
查看>>
mongodb基本操作
查看>>
工具使用——印象(汇总)
查看>>