Live2D

2022/10/24 考试

又爆了/kk 虽然 T2 考试时没有做出来,但是因为这纯粹是我脑瘫,就不写了。

比赛链接

T3

Desciption

给出 \(n\) 个集合,有 \(m\) 次操作,如下:

  • 给出 \(l,r,c\),往 \([l,r]\) 这个区间的集合加入 \(c\) 这个元素。

  • 给出 \(l,r\),查询 \([l,r]\) 集合的并的不同颜色个数。

\(n,m\le 10^5\)

Solution

其实似乎也不是太难,也不知道为什么也想不出来。/kk

我们考虑维护一种颜色的每个极长未出现段,那么一次查询的答案就是不同颜色个数减去完全包含它的未出现极长段的个数。

那么我们可以考虑用 set 去维护这个极长未出现段,然后用 cdq 或者 KD-tree 之类的实现二维查值就好了。

复杂度 \(\Theta(n\log^2 n)\)

Code



#include <bits/stdc++.h>
using namespace std;
     
#define Int register int
#define MAXN 100005
     
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,m;
struct node{
	int l,r,c;
	bool operator < (const node &p)const{return l < p.l;}
};
vector <node> seq;

#define pii pair<int,int>
#define se second
#define fi first

struct BIT{
	int sum[MAXN];
	int lowbit (int x){return x & (-x);}
	void modify (int x,int v){for (Int i = x;i <= n;i += lowbit (i)) sum[i] += v;}
	int query (int x){int res = 0;for (Int i = x;i;i -= lowbit (i)) res += sum[i];return res;}
	void backit (int x){for (Int i = x;i <= n;i += lowbit (i)) sum[i] = 0;}
}tree;

int ans[MAXN];
struct ODT{
	set <pii> Sta;
	void split (int x){
		auto it = Sta.lower_bound ({x,x});
		if ((it == Sta.end() && it -> fi == x) || it == Sta.begin() || (-- it) -> se < x) return ;
		pii tmp = *it;
		seq.push_back (node{tmp.fi,tmp.se,1}),seq.push_back (node{tmp.fi,x - 1,-1}),seq.push_back (node{x,tmp.se,-1});
		Sta.erase (it),Sta.insert ({tmp.fi,x - 1}),Sta.insert ({x,tmp.se});
	}
	void coverit (int l,int r){
		split (l),split (r + 1);
		auto beg = Sta.lower_bound ({l,l}),lst = Sta.lower_bound ({r + 1,r + 1}),now = beg;
		while (now != lst) seq.push_back (node{now -> fi,now -> se,1}),++ now;
		Sta.erase (beg,lst);
	}
}T[MAXN];

void solve (int l,int r){
	if (l == r) return ;
	int mid = l + r >> 1;
	solve (l,mid),solve (mid + 1,r);
	for (Int i = l,j = mid + 1;j <= r;++ j){
		while (j <= r && seq[j].c <= 1) ++ j;
		if (j > r) break;
		while (i <= mid && seq[i].l <= seq[j].l){
			if (seq[i].c <= 1) tree.modify (n - seq[i].r + 1,seq[i].c);
			++ i;
		}
		ans[seq[j].c - 1] += tree.query (n - seq[j].r + 1);
	}
	for (Int i = l;i <= mid;++ i) if (seq[i].c <= 1) tree.backit (n - seq[i].r + 1);
	inplace_merge (seq.begin() + l,seq.begin() + mid + 1,seq.begin() + r + 1);
}

int cnt,opt[MAXN],ql[MAXN],qr[MAXN],val[MAXN],b[MAXN];

signed main(){
	freopen ("cover.in","r",stdin);
	freopen ("cover.out","w",stdout);
	read (n,m);
	for (Int i = 1;i <= m;++ i){
		read (opt[i],ql[i],qr[i]);
		if (opt[i] == 1) read (val[i]),b[++ cnt] = val[i];
	}
	sort (b + 1,b + cnt + 1),cnt = unique (b + 1,b + cnt + 1) - b - 1;
	for (Int i = 1;i <= m;++ i) if (opt[i] == 1) val[i] = lower_bound (b + 1,b + cnt + 1,val[i]) - b;
	seq.push_back (node{1,n,-cnt});
	for (Int i = 1;i <= cnt;++ i) T[i].Sta.insert ({1,n});
	for (Int i = 1;i <= m;++ i){
		if (opt[i] == 2) seq.push_back (node{ql[i],qr[i],i + 1});
		else T[val[i]].coverit (ql[i],qr[i]);
	}
	solve (0,seq.size() - 1);
	for (Int i = 1;i <= m;++ i) if (opt[i] == 2) write (ans[i] + cnt),putchar ('\n');
   	return 0;
}
posted @ 2022-10-24 20:11  Dark_Romance  阅读(27)  评论(0编辑  收藏  举报