[Ynoi2014] 等这场战争结束之后
非常暴力的做法:每个点维护一颗平衡树,然后启发式合并。
但是这样的暴力做法会被回溯操作卡飞天。
先建出一棵操作树,将回溯操作简化为回退一次操作。
思考平衡树的劣势在哪里,合并和询问的复杂度极其不平衡。
想到平衡复杂度,那就只好分块了。
每个点维护一个值域分块,记录 \(cnt_{i, j}\) 为 \(i\) 点为根的子树中第 \(j\) 个值域块有多少个数。
连边和退边操作直接用可撤销并查集维护,合并/分裂时将两个根之间的贡献相加/减去。
询问时直接用根的 \(cnt\) 找到在哪个值域块,然后暴力遍历在找到值域块的所有数(包括不在当前树内的),注意离散化的时候不能去重,否则复杂度不正确。
那么你大概得到了一个时间 \(O(nB\log n)\),空间 \(O(\frac{n^2}{B})\) 的东西。
发现这题卡空间,把 \(B\) 调大一点即可。还是过不去的话,注意 \(\frac{n}{B}\) 不是很大,把 \(cnt\) 开 short 立省一半空间。
Code:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <cctype>
#include <vector>
#include <queue>
#include <bitset>
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define st first
#define nd second
using namespace std;
typedef long long ll;
typedef pair <int, int> Pii;
const int INF=0x3f3f3f3f;
const int cp=998244353;
inline int mod(int x){if(x>=cp) x-=cp;if(x<0) x+=cp;return x;}
inline void plust(int &x, int y){x=mod(x+y);return ;}
inline void minut(int &x, int y){x=mod(x-y);return ;}
inline int read(){
char ch=getchar();int x=0, f=1;
while(!isdigit(ch)){if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'), x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline int ksm(int a, int b=cp-2){
int ret=1;
for(; b; b>>=1, a=1ll*a*a%cp)
if(b&1) ret=1ll*ret*a%cp;
return ret;
}
const int N=1e5+5;
const int M=4000;
int n, m, X[N], Y[N], bid[N], L[25], R[25], a[N], id[N], ans[N];
int siz[N], f[N], p[N], num[N], vis[N];
short cnt[N][25];
int find(int x){return (x^f[x])?find(f[x]):f[x];}
vi G[N], rub;
void calc(int x, int y, int op){for(int i=bid[1]; i<=bid[n]; ++i) cnt[x][i]+=op*cnt[y][i];}
bool merge(int x, int y){
int fx=find(x), fy=find(y);if(fx==fy) return 0;
if(siz[fx]<siz[fy]) swap(fx, fy);
rub.pb(fy);f[fy]=fx, siz[fx]+=siz[fy];
calc(fx, fy, 1);
return 1;
}
void reback(){
int fy=rub.back();rub.pop_back();
calc(f[fy], fy, -1), siz[f[fy]]-=siz[fy], f[fy]=fy;
}
int query(int x, int y){
x=find(x);
int i=0, s=0;for(; i<=bid[n]&&s+cnt[x][i]<y; ++i) s+=cnt[x][i];
if(i>bid[n]) return -1;
for(int j=L[i]; j<=R[i]; ++j) if(find(num[j])==x&&(++s)==y) return p[j];
return 0;
}
void dfs(int x){
bool flg=0;
if(Y[x]>0) flg=merge(X[x], Y[x]);
else if(Y[x]<0) ans[x]=query(X[x], -Y[x]);
for(auto v:G[x]) dfs(v);
if(flg) reback();
}
signed main(){
n=read(), m=read();
for(int i=1; i<=n; ++i)
a[i]=p[i]=read(), siz[f[i]=i]=1;
sort(p+1, p+n+1);
for(int i=1, pos; i<=n; ++i)
pos=lower_bound(p+1, p+n+1, a[i])-p,
a[i]=pos+(vis[pos]++), num[a[i]]=i;//, printf("%d ", a[i]);puts("");
for(int i=1, c=0; i<=n; i+=M, ++c)
for(int j=0; j<M&&i+j<=n; ++j)
L[c]=i, R[c]=i+j, bid[i+j]=c;
for(int i=1; i<=n; ++i) cnt[i][bid[a[i]]]=1;//printf("%d\n", bid[n]);
for(int i=1, pos=0; i<=m; ++i){
int op=read();
if(op==1) X[i]=read(), Y[i]=read(), G[pos].pb(i), pos=id[i]=i;
if(op==2) pos=id[i]=id[read()];
if(op==3) X[i]=read(), Y[i]=-read(), G[pos].pb(i), pos=id[i]=i;
}
dfs(0);
for(int i=1; i<=m; ++i) if(Y[i]<0) printf("%d\n", ans[i]);
return 0;
}
[Ynoi2014] 等这场战争结束之后的更多相关文章
- [Ynoi2014]不归之人与望眼欲穿的人们
题目大意: 给定一个序列,每次单点修改一个数,或给定$x$,询问最短的or起来大于等于$x$的区间的长度(不存在输出-1). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归 ...
- [Ynoi2015]即便看不到未来
题目大意: 给定一个序列,每次询问,给出一个区间$[l,r]$. 设将区间内的元素去重后重排的数组为$p$,求$p$中长度为$1\sim 10$的极长值域连续段个数. 长度为$L$的极长值域连续段的定 ...
- [Ynoi2015]纵使日薄西山
题目大意: 给定一个序列,每次单点修改,然后进行询问. 定义一次操作为,选择一个位置$x$,将这个位置的数和左边.右边两个位置的数(不存在则忽略)各减去1,然后和0取max. 对序列中最大的位置进行一 ...
- [Ynoi2015]盼君勿忘
题目大意: 给定一个序列,每次查询一个区间\([l,r]\)中所有子序列分别去重后的和\(\bmod p\)(每次询问模数不同). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后 ...
- [Ynoi2015]我回来了
题目大意: 给定一张无向无权图,每次给定若干个二元组\((x_i,y_i)\),定义点\(u\)满足条件,当且仅当存在\(i\),并满足\(dist(u,x_i)\leqslant y_i\)(\(d ...
- [Ynoi2015]此时此刻的光辉
题目大意: 给定一个序列,每次询问一段区间的数的乘积的约数个数. 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐 ...
- 题解 P5072 【[Ynoi2015] 盼君勿忘】
在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘 ...
- 东大OJ-1544: GG的战争法则
题目描述 你在桥上看风景 看风景的人在楼上看你 明月装饰了你的窗子 你装饰了我的梦 这是GG在长坂坡发出的感叹. 三年前GG莫名的穿越到了三国时期,在这三年里他看尽了各种杀戮,心里早已麻木.GG他渴望 ...
- BAT线下战争:巨额投资或培养出自己最大对手(包括美团、58、饿了么在内的公司都在计划推出自己的支付工具和金融产品,腾讯只做2不做O)
BAT线下战争:巨额投资或培养出自己最大对手 2015年10月12日09:49 <财经>杂志 我有话说(18人参与) 收藏本文 BAT大举投资线下公司,看似咄咄逼人 ...
- Swift开发小技巧--自定义转场动画
自定义转场动画 个人理解为重写了被弹出控制器的modal样式,根据自己的样式来显示modal出来的控制器 例:presentViewController(aVC, animated: true, co ...
随机推荐
- .NET中的线程本地存储(TLS)与AsyncLocal(一)
一.TLS 线程本地存储(Thread Local Storage),字面意思就是专属某个线程的存储空间.变量大体上分为全局变量和局部变量,一个进程中的所有线程共享地址空间,这个地址空间被划分为几个固 ...
- jeecgboot前端按钮角色权限控制(是否隐藏)
官方文档 http://doc.jeecg.com/2044038 解决办法 首先需要修改前端代码,在想获得权限控制的按钮组件中使用指令 v-has="''". 代码示例: < ...
- Web前端入门第 29 问:CSS 盒模型:网页布局的基石
在 Web 网页开发中,盒模型(Box Model) 是 CSS 的核心概念,它决定了每个 HTML 元素在页面中占据的空间和布局方式. 无论是文本.图片还是按钮,浏览器都会将它们视为一个矩形盒子,并 ...
- CH579M 以太网接收死机
CH579M进行以太网连接服务器时,可以正常连接,收发数据也可以. 但是当接收的数据量到达512左右时,CH579M就会无响应,问题出在工程设置上. 正确的设置↓↓↓↓↓ 错误的设置↓↓↓↓↓
- (原创)[开源][.Net Framework 4.5] SimpleMVVM(极简MVVM框架)更新 v1.1,增加NuGet包
一.前言 意料之外,也情理之中的,在主业是传统行业的本人,技术的选型还是落后于时代. 这不,因现实需要,得将大库中的 WPF MVVM 相关部分功能拆分出来独立使用,想着来都来了,就直接开源得了,顺便 ...
- 一条 SQL 语句在 MySQL 中的执行过程
一条 SQL 语句在 MySQL 中的执行过程 当一条 SQL 语句被提交到 MySQL 时,它会经历多个步骤,包括解析.优化.执行等.以下以 SELECT 语句为例,详细描述整个执行流程. 1. 客 ...
- GPFS并行文件系统部署实践
环境 ubuntu22.04 试用版下载链接 https://www.ibm.com/cn-zh/products/storage-scale 我的版本:Storage_Scale_Developer ...
- K8s新手系列之K8s架构
应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署 互联网早期,会直接将应用程序部署在物理机上 优点:简单,不需要其它技术的参与缺点:不能为应用程序定义资源使用边界,很难合理地分 ...
- 代码随想录第八天| Leecode 344. 反转字符串、Leecode 541 反转字符串 II
Leecode 344 反转字符串 题目链接:https://leetcode.cn/problems/reverse-string/description/ 题目描述 编写一个函数,其作用是将输入的 ...
- jdbcTemplate之“rowMapper内部类写法”
jdbcTemplate的rowMapper内部类写法 String sql ="select sku,feature from product"List<Product&g ...