「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. Linux sed使用方法

    目录 sed处理流程 测试数据 sed命令格式 sed命令行格式 行定位 定位1行 定位区间行(多行) 定位某一行之外的行 定位有跨度的行 操作命令 -a (新增行) -i(插入行) -c(替代行) ...

  2. Linux系统tree工具

    当用户在linux平台中需要需要查看一个非当前目录的目录下有哪些文件和子文件时,最普通的办法就是cd该目录,然后再ls,这个操作令人不舒适,因为查看完以后,用户还需要切换到原来的目录.现在介绍一款非常 ...

  3. 01-学习vue前的准备工作

    起步 1.扎实的HTML/CSS/Javascript基本功,这是前置条件. 2.不要用任何的构建项目工具,只用最简单的<script>,把教程里的例子模仿一遍,理解用法.不推荐上来就直接 ...

  4. 数据处理 array json 格式 转换成 数组形式

    处理这种数据应该使用的方式是 this.cities= res.data.data.cities.sort((a,b)=>{ //排序 进行字母排序 return a.pinyin[0].cha ...

  5. Laravel数据库操作的三种方式

    http://blog.csdn.net/zls986992484/article/details/52824962

  6. MyCat数据库中间件 - 分库

    MyCat MyCat用于解耦分布式数据库与java,比如分库分表以后,需要查询某条数据时,需要java根据需要查的数据先计算去哪个库查,然而有了Mycat就不用自己计算怎么存储,怎么查询了.MyCa ...

  7. Python rsa公私钥生成 rsa公钥加解密(分段加解密)-私钥加签验签实战

    一般现在的SAAS服务提供现在的sdk或api对接服务都涉及到一个身份验证和数据加密的问题.一般现在普遍的做法就是配置使用非对称加密的方式来解决这个问题,你持有SAAS公司的公钥,SAAS公司持有你的 ...

  8. 用织梦建站如何去掉a这个目录,还有内容页的a

    1.另外建一个站点,将物理路径直接指向a即可. 2.去掉文章页生成的带a的路径: 只需要这一句话:  function='str_replace("/a","" ...

  9. 去掉dede织梦position当前位置最后一个箭头的方法

    理论是,dede的当前位置标签{dedefield name='position'}结构是 首页 > 主栏目 > 子栏目 > ,这就说明,而箭头符号字段数据都是在后台设置后存储在数据 ...

  10. 莫烦theano学习自修第二天【激励函数】

    1. 代码如下: #!/usr/bin/env python #! _*_ coding:UTF-8 _*_ import numpy as np import theano.tensor as T ...