首页 > 其他分享 > [Ynoi2014] 等这场战争结束之后

[Ynoi2014] 等这场战争结束之后

时间:2023-02-10 19:45:40浏览次数:63  
标签:cnt cp const int Ynoi2014 这场 战争 include define

题传

非常暴力的做法:每个点维护一颗平衡树,然后启发式合并。

但是这样的暴力做法会被回溯操作卡飞天。

先建出一棵操作树,将回溯操作简化为回退一次操作。

思考平衡树的劣势在哪里,合并和询问的复杂度极其不平衡。

想到平衡复杂度,那就只好分块了。

每个点维护一个值域分块,记录 \(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;
}

标签:cnt,cp,const,int,Ynoi2014,这场,战争,include,define
From: https://www.cnblogs.com/sizeof127/p/17110140.html

相关文章

  • 欧陆战争6修改
    新人第一次写修改教程,写的不好见谅QWQ靡不有初,鲜克有终。————《诗经·大雅》一、关于准备工作如果您没有安装MT管理器,请移步https://mt2.c......
  • [Ynoi2014] 置身天上之森
    题传其实做过由乃打扑克的话思路并不难。但写代码的时候把写由乃打扑克的bug全部复现了属实难蚌注意到线段树不同区间长度是\(O(\logn)\)的,因此我们对于每种长度建......
  • 关于清远乡村小微企业未来发展,这场发布会信息量大
    党的二十大报告指出,全面推进乡村振兴,加快建设农业强国,扎实推动乡村产业、人才、文化、生态、组织振兴。中央农村工作会议提出,产业振兴是乡村振兴的重中之重,要落实产业帮扶政......
  • 别错过!这场干货满满的操作系统产业峰会回顾来了
    12月28日操作系统产业峰会2022以线上直播的方式圆满举办作为操作系统产业界的年度盛会本次大会干货满满精彩纷呈!赶紧来一起回顾吧!25位重磅嘉宾出席​4大系列重磅内容亮相​2......
  • 直播回顾 | 这场直播回答了手机银行人机验证的必要性和可行性
    人机验证作为手机银行验证体系中重要的一环,其验证码的安全性以及用户体验成为了主要考验。12月22日,顶象资深解决方案专家鳯羽就手机银行的人机验证解决方案讲起,从人机验......
  • 就在今晚!科技公司如何予力公益?赶紧收看这场直播吧!
    (本文阅读时间:3分钟)想知道微软如何做公益吗?那科技怎样予力公益呢?本期公益演讲将以微软在公益领域的实践带大家一同了解,敬请期待!微软ATPPublic100微软AlTalentProgram主办......
  • 2279. 网络战争
    2279.网络战争二分求那个平均值、如果比平均值小,那肯定要算上,其他没有算上的边,跑一个最小流就可以了。也就是取出一些边之后,然后求出必须要拿出来的边。#include<bit......
  • 海量数据战争——谁能赢得未来?
    时至今日,海量数据时代的来临已经毋庸置疑,尤其是在互联网、电信、金融等行业,几乎已经到了“数据就是业务本身”的地步。在这其中,还挟裹着一个更为重要的趋势,即数据的社会化,......
  • 2279. 网络战争
    题目链接2279.网络战争给出一个带权无向图\(G=(V,E)\),每条边\(e\)有一个权\(w\_e\)。求将点\(s\)和点\(t\)分开的一个边割集\(C\),使得该割集的平均边权最小......
  • 【比赛】NOIP模拟5 战争 肥胖 分摊 修路
    T1[图论:最大团BK算法]给出n个点,和它们所属的集合,规定同一集合内部的点没有边连接,不同集合任一点有边连接,给出K对关系的取反,找到图中最大团,输出大小和集合元素。(K<=20,n<=1......