【BZOJ】3626 [LNOI2014]LCA
【算法】树链剖分+线段树(区间加值,区间求和)
【题解】http://hzwer.com/3891.html
中间不要取模不然相减会出错。
血的教训:线段树修改时标记下传+上传,查询时下传。如果修改时标记不下传,下面的结果就会覆盖上面的标记上传造成的影响。
读入后全部排序(离线处理)
链剖之后按顺序每个solve_insert(1,j),对于每次的z询问solve_sum(1,z)。
LCA其实就是两点到达根节点的路径的最近交点。
差分思想的运用:将区间差转为r-(l-1)。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=,MOD=;
int n,first[maxn],tot=,top[maxn],deep[maxn],pos[maxn],q,ansz[maxn],size[maxn],f[maxn],dfsnum=;
long long anss[maxn*];
struct edge{int from,v;}e[maxn*];
struct node{int l,r,delta,sum;}t[maxn*];
struct numbers{int num,ord;bool flag;}num[maxn*];
void insert(int u,int v)
{tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
bool cmp(numbers a,numbers b)
{return a.num<b.num;}
void dfs1(int x,int fa)
{
size[x]=;
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa)
{
int y=e[i].v;
f[y]=x;
deep[y]=deep[x]+;
dfs1(y,x);
size[x]+=size[y];
}
}
void dfs2(int x,int tp,int fa)
{
pos[x]=++dfsnum;
top[x]=tp;
int k=;
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa&&size[e[i].v]>size[k])k=e[i].v;
if(k==)return;
dfs2(k,tp,x);
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa&&e[i].v!=k)dfs2(e[i].v,e[i].v,x); }
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].delta=;t[k].sum=;
if(l==r)return;
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
t[k].sum=t[k<<].sum+t[k<<|].sum;
}
void add(int k,int l,int r)
{
int left=t[k].l,right=t[k].r;
if(l<=left&&right<=r)
{
t[k].delta++;
t[k].sum+=right-left+;
return;
}
if(t[k].delta)
{
t[k<<].delta+=t[k].delta;
t[k<<].sum+=(t[k<<].r-t[k<<].l+)*t[k].delta;
t[k<<|].delta+=t[k].delta;
t[k<<|].sum+=(t[k<<|].r-t[k<<|].l+)*t[k].delta;
t[k].delta=;
}
int mid=(left+right)>>;
if(l<=mid)add(k<<,l,r);
if(r>mid)add(k<<|,l,r);
t[k].sum=t[k<<].sum+t[k<<|].sum;
}
long long query(int k,int l,int r)
{
int left=t[k].l,right=t[k].r;
if(l<=left&&right<=r)return t[k].sum;
if(t[k].delta)
{
t[k<<].delta+=t[k].delta;
t[k<<].sum+=(t[k<<].r-t[k<<].l+)*t[k].delta;
t[k<<|].delta+=t[k].delta;
t[k<<|].sum+=(t[k<<|].r-t[k<<|].l+)*t[k].delta;
t[k].delta=;
}
int mid=(left+right)>>;
long long ans=;
if(l<=mid)ans=query(k<<,l,r);
if(r>mid)ans+=query(k<<|,l,r);
return ans;
}
void solve_ins(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
add(,pos[top[x]],pos[x]);
x=f[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
add(,pos[x],pos[y]);
}
long long solve_sum(int x,int y)
{
long long ans=;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
ans+=query(,pos[top[x]],pos[x]);
x=f[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
ans+=query(,pos[x],pos[y]);
return ans;
}
int main()
{
scanf("%d%d",&n,&q);
int u;
for(int i=;i<=n;i++)
{
scanf("%d",&u);
insert(u+,i);
insert(i,u+);
}
int ll,rr,zz;
for(int i=;i<=q;i++)
{
scanf("%d%d%d",&ll,&rr,&zz);ll++;rr++;zz++;
ansz[i]=zz;
num[i*-].num=ll-;num[i*-].ord=i;num[i*-].flag=;
num[i*].num=rr;num[i*].ord=i;num[i*].flag=;
}
sort(num+,num+q*+,cmp);
build(,,n);dfs1(,-);dfs2(,,-);
int now=;
memset(anss,,sizeof(anss));
for(int i=;i<=q*;i++)
{
if(num[i].num>now)
for(int j=now+;j<=num[i].num;j++)solve_ins(,j);
now=num[i].num;
if(num[i].flag)anss[num[i].ord]+=solve_sum(,ansz[num[i].ord]);
else anss[num[i].ord]-=solve_sum(,ansz[num[i].ord]);
} for(int i=;i<=q;i++)printf("%lld\n",anss[i]%MOD);
return ;
}
【BZOJ】3626 [LNOI2014]LCA的更多相关文章
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- bzoj 3626: [LNOI2014]LCA 离线+树链剖分
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 124[Submit][Status] ...
- BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...
- 【BZOJ】3052: [wc2013]糖果公园
http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...
- 【BZOJ】3319: 黑白树
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...
- 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法
[题意]给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值.n,m<=5*10^4,0<=ai<=10^9. [算法]树分块+ ...
- 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...
- 【BZOJ】1013: [JSOI2008]球形空间产生器sphere
[BZOJ]1013: [JSOI2008]球形空间产生器sphere 题意:给n+1个n维的点的坐标,要你求出一个到这n+1个点距离相等的点的坐标: 思路:高斯消元即第i个点和第i+1个点处理出一个 ...
随机推荐
- /proc/meminfo中meminfo的计算方法
/proc/meminfo里的可使用内存的计算没有那么简单,并不是简单的free和page cache的加和 free + pagecache 以此为基准 但是需要减去一些内存:首先要减去系统预留的内 ...
- mysql学习之主从复制
该文使用mysql5.5 centos6.5 64位 一.主从复制的作用 1.如果主服务器出现问题,可以快速切换到从服务器. 2.对与实时性要求不高或者更新不频繁的应用可以在从服务器上执行查询操作,降 ...
- 【问题解决】Project facet Java version 1.7 (或者1.8)is not supported.
在移植eclipse项目时,如果遇到 “Project facet Java version 1.7 is not supported.” 项目中的jdk1.7不支持.说明项目是其他版本jdk编译的, ...
- 【】Python】异常处理try...except、raise
一.try...except 有时候我们写程序的时候,会出现一些错误或异常,导致程序终止.例如,做除法时,除数为0,会引起一个ZeroDivisionError 例子: 1 2 3 4 a=10 b= ...
- BZOJ 1004 Cards(Burnside引理+DP)
因为有着色数的限制,故使用Burnside引理. 添加一个元置换(1,2,,,n)形成m+1种置换,对于每个置换求出循环节的个数, 每个循环节的长度. 则ans=sigma(f(i))/(m+1) % ...
- 【bzoj5008】方师傅的房子 计算几何
题目描述 给出一个凸多边形,多次询问某个点是否在这个凸多边形的内部,强制在线. 输入 第一行一个数n,接下来n行,每行两个整数x,y.输入按照逆时针顺序输入一个凸包. 接下来一个数m,最后有m行, ...
- BZOJ4299 Codechef FRBSUM(主席树)
感觉非常不可做,于是考虑有什么奇怪的性质. 先考虑怎么求子集和mex.将数从小到大排序,假设已经凑出了0~n的所有数,如果下一个数>n+1显然mex就是n+1了,否则若其为x则可以凑出1~n+x ...
- CentOS7 防火墙配置firewall-cmd
firewalld(Dynamic Firewall Manager of Linux systems,Linux系统的动态防火墙管理器)服务是默认的防火墙配置管理工具. firewall-cmd 是 ...
- [HAOI2010]计数 数位DP+组合数
题面: 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等. ...
- Android 内核--Binder架构分析
一.Binder架构 在Android中,Binder用于完成进程间通信(IPC),即把多个进程关联在一起.比如,普通应用程序可以调用音乐播放服务提供的播放.暂停.停止等功能.Binder工作在Lin ...