CF848C Goodbye Souvenir

https://www.luogu.com.cn/problem/CF848C
问题可以转化成

∑ i − p r e i [ p r e i > = L , i < = R ] \sum i - pre_{i}[pre_i>=L,i<=R] iprei[prei>=L,i<=R]
再加上修改有一维是时间 t t t
就是一个三维偏序
code:

#include<bits/stdc++.h>
#define lowbit(x) (x & -x)
#define N 1000005
#define ll long long
using namespace std;
set<int> mp[N];
int gpre(int x, int y) {
	set<int>::iterator it = mp[x].lower_bound(y); it --;
	return *it; 
}
int gnxt(int x, int y) {
	return *(mp[x].upper_bound(y));
}

int n, pre[N], nxt[N], col[N], m, sz;

ll tree[N], ANS[N];
void update(int x, int y) { if(x)
	for(; x <= n; x += lowbit(x)) tree[x] += y;
}
ll query(int x) {
	ll ret = 0;
	for(; x; x -= lowbit(x)) ret += tree[x];
	return ret;
}
struct A {
	int opt, x, y, val, id;
} a[N];
void change(int x, int y) {
	a[++ sz] = A{0, x, pre[x], -(x - pre[x]), 0};
	pre[x] = y;
	a[++ sz] = A{0, x, pre[x], x - pre[x], 0};
}
int cmp(A x, A y) {
	if(x.opt != y.opt) return x.opt < y.opt;
	if(x.opt) return x.y < y.y;
	return x.x < y.x;
}
void cdq(int l, int r) {
	if(l == r) return;
	int mid = (l + r) >> 1;
	cdq(l, mid), cdq(mid + 1, r);
	sort(a + mid + 1, a + r + 1, cmp);
	int pos = l - 1;
	for(int i = mid + 1; i <= r; i ++) if(a[i].opt == 1){
		while(pos < mid && (a[pos + 1].opt == 1 || a[pos + 1].x <= a[i].y)) {
			pos ++;
			if(!a[pos].opt) update(a[pos].y, a[pos].val);
		} 
		ANS[a[i].id] += query(n) - query(a[i].x - 1);
	}
	for(int i = l; i <= pos; i ++) if(!a[i].opt) update(a[i].y, - a[i].val);
	sort(a + l, a + r + 1, cmp);
}
int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) mp[i].insert(0), mp[i].insert(n + 1); 
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &col[i]);
		mp[col[i]].insert(i); 
	}
	for(int i = 1; i <= n; i ++)
		pre[i] = gpre(col[i], i), nxt[i] = gnxt(col[i], i), a[++ sz] = A{0, i, pre[i], i - pre[i], 0};
	int ha = 0;
	for(int i = 1; i <= m; i ++) {
		int opt, x, y;
		scanf("%d%d%d", &opt, &x, &y);
		if(opt == 1) {
			int pree = gpre(y, x), nxtt = gnxt(y, x);
			mp[col[x]].erase(x), mp[y].insert(x);
			col[x] = y;
			if(nxt[x] != n + 1) change(nxt[x], pre[x]);
			if(pre[x]) nxt[pre[x]] = nxt[x];
			
			if(nxtt != n + 1) change(nxtt, x);
			if(pree) nxt[pree] = x;
			change(x, pree);
			nxt[x] = nxtt;
		} else a[++ sz] = A{1, x, y, 0, ++ ha};
	}
	cdq(1, sz);
	for(int i = 1; i <= ha; i ++) printf("%lld\n", ANS[i]);
	return 0;
}
posted @ 2021-03-29 11:19  lahlah  阅读(32)  评论(0编辑  收藏  举报