「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」大森林 解题报告的更多相关文章

  1. @loj - 2092@ 「ZJOI2016」大森林

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...

  2. loj2092 「ZJOI2016」大森林

    ref不是太懂-- #include <algorithm> #include <iostream> #include <cstring> #include < ...

  3. 「THUSCH 2017」大魔法师 解题报告

    「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...

  4. 「JLOI2015」管道连接 解题报告

    「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...

  5. 「NOI2017」蚯蚓排队 解题报告

    「NOI2017」蚯蚓排队 这题真的草 你考虑\(k\)这么小,每次合并两个串,增加的有用串的数量是\(O(k^2)\)的,暴力加入这些串,求一下这些串的Hash值,塞到Hash表里面去 这里采用类似 ...

  6. 「FJOI2016」神秘数 解题报告

    「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...

  7. 「SCOI2016」背单词 解题报告

    「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...

  8. 「NOI2015」寿司晚宴 解题报告

    「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...

  9. 「SCOI2015」国旗计划 解题报告

    「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...

随机推荐

  1. 福州大学软件工程1816 | W班 第5次作业成绩排名

    写在前面 汇总成绩排名链接 1.作业链接 第五次作业--项目选题报告(团队) 2.评分准则 本次作业映射总分为100分+贡献度得分,由以下部分组成: 选题报告内容(10分) 本组评审表设计(5分) 现 ...

  2. Linux系统mysql使用(二)

    一.查看某数据库的表 # 假设此时数据库名为hiveuse hive; show tables;

  3. java 工具

    JClassLib 4.2 发布了,该版本支持 Java 7 和 Java 8 的类文件属性查看. JClassLib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Cla ...

  4. [转帖]Linux的标准输入 标准输出和错误输出

    Linux标准输入.输出和错误和文件重定向 专题 https://www.cnblogs.com/softidea/p/3965093.html 感觉自己对 这一块的理解一直不好 昨天同事给了一个 b ...

  5. WSL Windows subsytem linux 的简单学习与使用

    1. win10 1709 以上的版本应该都增加上了 ctrl +r 运行 winver 查看版本 2. 添加删除程序 增加 wsl 增加一个功能 3. 打开cmd 输入 bash 即可 4. 可以将 ...

  6. 【apache2】AH00543: httpd: bad user name apache

    当启动 apache 时,出现一下异常:AH00543: httpd: bad user name daemon 解决方法:            #groupadd daemon          ...

  7. php 将数组转换网址URL参数

    $array =array ( 'id' =123, 'name' = 'dopost' );echo http_build_query( $array );//得到结果id=123name=dopo ...

  8. WPF实现Windows资源管理器(附源码)

      今天我来写一篇关于利用WPF来实现Windows的资源管理器功能,当然只是局部实现这个功能,因为在很多时候我们需要来实现对本机资源的管理,当然我们可以使用OpenFileDialog dialog ...

  9. 除了binlog2sql工具外,使用python脚本闪回数据(数据库误操作)

    利用binlog日志恢复数据库误操作数据 在人工手动进行一些数据库写操作的时候(比方说数据修改),尤其是一些不可控的批量更新或删除,通常都建议备份后操作.不过不怕万一,就怕一万,有备无患总是好的.在线 ...

  10. Spring注解 系列之Spring常用注解总结

    参考:Spring系列之Spring常用注解总结 (1) Resource 默认是byName的方式进行bean配置,@AutoWired默认是按照byType的方式进行装配bean的:(2)Comp ...