「ZJOI2016」大森林 解题报告
「ZJOI2016」大森林
神仙题...
很显然线段树搞不了
考虑离线操作
我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试
显然操作0,1都可以拆成差分的形式,就是加入和删除
因为保证了操作2的合法性,我们不妨先不计合法性把所有点加到树中
显然每个点要连到在这个点之前的离这个点时间上最近那个1操作的点上
然后可以发现移动时1操作相当于很多个点换根
我们可以对每个1操作建一个虚点,然后就可以很方便换根了
那么如何保证查询操作呢?
可以把每个1操作的虚点大小设成0(代表它父亲边的直接长度),并按时间串起来。
这样,一个虚点的虚点儿子的子树的点其实也是它的子树了,查询的时候差dis[u]+dis[v]-dis[lca]*2就可以了
是不是以为这个0操作的区间限制就没有用了?
其实不是,注意到1操作的点可能还没出现...这时候就要把1操作删掉
Code:
#include <cstdio>
#include <cctype>
#include <algorithm>
using std::min;
using std::max;
const int N=3e5+10;
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
int ans[N],n,m,_n,_m,q,p[N],node,ti[N],tot,L[N],R[N];
struct koito_yuu
{
int pos,op,u,v;
koito_yuu(){}
koito_yuu(int Pos,int Op,int U,int V){pos=Pos,op=Op,u=U,v=V;}
bool friend operator <(koito_yuu a,koito_yuu b){return a.pos==b.pos?a.op<b.op:a.pos<b.pos;}
}yuu[N];
#define ls ch[now][0]
#define rs ch[now][1]
#define fa par[now]
int sum[N],ch[N][2],par[N],siz[N];
bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
int identity(int now){return ch[fa][1]==now;}
void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
void updata(int now){sum[now]=sum[ls]+sum[rs]+siz[now];}
void Rotate(int now)
{
int p=fa,typ=identity(now);
connect(p,ch[now][typ^1],typ);
if(isroot(p)) connect(par[p],now,identity(p));
else fa=par[p];
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now)
{
for(;isroot(now);Rotate(now))
if(isroot(fa))
Rotate(identity(now)^identity(fa)?now:fa);
}
int access(int now)
{
int las=0;
for(;now;las=now,now=fa) splay(now),rs=las,updata(now);
return las;
}
int LCA(int x,int y)
{
access(x);
return access(y);
}
void link(int x,int y)
{
access(x),splay(x);
par[x]=y;
}
void cat(int x)
{
access(x),splay(x);
par[ch[x][0]]=0;
ch[x][0]=0;
}
int qry(int x)
{
access(x),splay(x);
return sum[x];
}
int query(int x,int y)
{
int lca=LCA(x,y);
return qry(x)+qry(y)-(qry(lca)<<1);
}
int main()
{
read(n),read(m);
L[1]=1,R[1]=n,node=1,++tot;
for(int op,l,r,x,u,v,i=1;i<=m;i++)
{
read(op);
if(op==0) ++node,read(L[node]),read(R[node]),p[node]=i;
else if(op==1)
{
ti[++tot]=i;
link(tot,tot-1);
read(l),read(r),read(x);
l=max(L[x],l),r=min(R[x],r);
if(l>r) continue;
yuu[++q]=koito_yuu(l,-1,x,tot);
yuu[++q]=koito_yuu(r+1,0,x,tot);
}
else
{
read(x),read(u),read(v);
yuu[++q]=koito_yuu(x,++_n,u,v);
}
}
_m=tot;
for(int i=2;i<=node;i++)
{
int pos=std::upper_bound(ti+1,ti+1+_m,p[i])-ti-1;
siz[++tot]=1,sum[tot]=1;
link(tot,pos);
}
std::sort(yuu+1,yuu+1+q);
for(int j=1,i=1;i<=n;i++)
{
while(yuu[j].pos==i)
{
int u=yuu[j].u+_m-1,v=yuu[j].v;
if(u==_m) u=1;
if(yuu[j].op==-1)
{
cat(v);
link(v,u);
}
else if(yuu[j].op==0)
{
cat(v);
link(v,v-1);
}
else ans[yuu[j].op]=query(u,v==1?1:v+_m-1);
++j;
}
}
for(int i=1;i<=_n;i++) printf("%d\n",ans[i]);
return 0;
}
2019.3.11
「ZJOI2016」大森林 解题报告的更多相关文章
- @loj - 2092@ 「ZJOI2016」大森林
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...
- loj2092 「ZJOI2016」大森林
ref不是太懂-- #include <algorithm> #include <iostream> #include <cstring> #include < ...
- 「THUSCH 2017」大魔法师 解题报告
「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...
- 「JLOI2015」管道连接 解题报告
「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...
- 「NOI2017」蚯蚓排队 解题报告
「NOI2017」蚯蚓排队 这题真的草 你考虑\(k\)这么小,每次合并两个串,增加的有用串的数量是\(O(k^2)\)的,暴力加入这些串,求一下这些串的Hash值,塞到Hash表里面去 这里采用类似 ...
- 「FJOI2016」神秘数 解题报告
「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...
- 「SCOI2016」背单词 解题报告
「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...
- 「NOI2015」寿司晚宴 解题报告
「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...
- 「SCOI2015」国旗计划 解题报告
「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...
随机推荐
- 学习bootstrap3
官方手册(英文):http://getbootstrap.com/docs/3.3/getting-started/ 中文文档:https://v3.bootcss.com/getting-start ...
- CMMI摘要
CMMI_百度百科https://baike.baidu.com/item/CMMI CMMI分为哪几个等级?CMMI等级介绍_百度经验https://jingyan.baidu.com/articl ...
- Jenkins Installing and migration
JAVA_Zookeeper_hadoop - CSDN博客https://blog.csdn.net/wangmuming Installing Jenkins on Red Hat distrib ...
- java依赖的斗争:依赖倒置、控制反转和依赖注入
控制反转(Inversion Of Controller)的一个著名的同义原则是由Robert C.Martin提出的依赖倒置原则(Dependency Inversion Principle),它的 ...
- [转帖]CS、IP和PC寄存器
https://www.cnblogs.com/zhuge2018/p/8466288.html 之前的理解不对 当然了 现在的理解也不太对.. CS.IP和PC寄存器 CS寄存器和IP寄存器: 首先 ...
- [转帖]SUSE Linux
历经坎坷多次易主,SUSE Linux路在何方? http://blog.itpub.net/11310314/viewspace-2638811/ 之前一直理不清楚 SUSE和RedHat的关系 甚 ...
- js怎么能取得多选下拉框选中的多个值?
方法:获取多选下拉框对象数组→循环判断option选项的selected属性(true为选中,false为未选中)→使用value属性取出选中项的值.实例演示如下: 1.HTML结构 1 2 3 4 ...
- python3 输出系统信息
一.安装psutil库 pip3 install psutil 二.代码 #!/usr/bin/python3 coding=utf-8 import psutil import uuid impor ...
- falsk sqlalchemy 自关联创建评论回复数据库
本项目在于创建类似微信上的评论回复功能的数据库 基类: from app import db from datetime import datetime class Basemadel(object) ...
- spring 在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property
spring 在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property