蒟蒻求条
查看原帖
蒟蒻求条
846041
__xxy_free_ioi__楼主2025/8/1 20:38

一直过不了样例,AI也不管用,请各位DALAO救救我!

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
#define VI vector<int>
#define sz(a) a.size()
#define all(a) a.begin(), a.end()
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)

struct BIT {
	int n;
	VI t;
	void init(int x) { n = x, t.resize(x + 2); }
	void add(int p, int d) { while (p <= n) t[p] += d, p += p & -p; }
	int ask(int p) {
		int res = 0;
		while (p) res += t[p], p -= p & -p;
		return res;
	}
};
struct Type { int x, y, v, op, id; }; // 询问类型

const int N = 3e5 + 2, INF = 1e9;

int n, m, idx, res[N], state[N]; // state -> 当前状态
Type q[5 * N], tmp[5 * N]; // q存差分点集 
BIT op_t, cdq_t; // 处理operate的BIT, 处理CDQ分治的BIT
set<int> s; // 便于快速查询左右第一个为0的点(影响区间 [L+1, p]~[p, R-1]

void Add(int x, int y, int v) { q[++idx] = {x, y, v, 0, 0}; }
void Add_sq(int x1, int y1, int x2, int y2, int d) {
	Add(x2, y2, d);
	if (x1 > 1) Add(x1 - 1, y2, -d);
	if (y1 > 1) Add(x2, y1 - 1, -d);
	if (x1 > 1 && y1 > 1) Add(x1 - 1, y1 - 1, d);
}
bool check(int l, int r) { return op_t.ask(r) - op_t.ask(l - 1) == r - l + 1; }
// check判断[l,r]是否全部是1 
void work(int p, int t) { // 操作下标,操作轮数 目的:完成操作影响  
	if (!state[p]) {
		auto it = s.upper_bound(p);
		int L = *prev(it), R = *it;
		s.insert(p);
		Add_sq(L + 1, p, p, R - 1, -(m - t)); // 关灯,产生负贡献 
	} else {
		s.erase(p);
		auto it = s.upper_bound(p);
		int L = *prev(it), R = *it;
		Add_sq(L + 1, p, p, R - 1, m - t); // 开灯产生正贡献 
	}
}
void cdq(int l, int r) { 
	// CDQ分治,计算所有满足(t1 <= t2 && x1 >= x2 && y1 >= y2)的点对(x2, y2)的贡献 
	if (l >= r) return;
	int mid = (l + r) >> 1, i = l, j = mid + 1, k = 0;
	cdq(l, mid), cdq(mid + 1, r);
	while (i <= mid || j <= r) 
		if (j > r || (i <= mid && q[i].x >= q[j].x)) {
			if (!q[i].op) cdq_t.add(q[i].y, q[i].v);
			tmp[++k] = q[i++];
		} else {
			if (q[j].op) res[q[j].id] += cdq_t.ask(n) - cdq_t.ask(q[j].y - 1);
			tmp[++k] = q[j++];
		}
	up(i1, l, mid) if (!q[i1].op) cdq_t.add(q[i1].y, -q[i1].v);
	for (int i1 = 1, j1 = l; i1 <= k; i1++, j1++) q[j1] = tmp[i1];
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	string ss;
	cin >> n >> m >> ss, op_t.init(n + 2), cdq_t.init(n + 2); 
	up(i, 1, n) state[i] = ss[i - 1] - '0';
	s.insert(0), s.insert(n + 1);
	Add_sq(1, n, 1, n, m); // 先多算一部分,再减掉 
	up(i, 1, n) if (state[i]) op_t.add(i, 1);
	up(i, 1, n) if (!state[i]) work(i, 0); // 计算 
	up(i, 1, m) {
		cin >> ss;
		if (ss[0] == 'q') {
			int a, b; cin >> a >> b, b--;
			if (check(a, b)) res[i] = -(m - i); // 先减掉多算的 
			q[++idx] = {a, b, 0, 1, i};
		} else {
			int x; cin >> x;
			state[x] ^= 1, work(x, i),
			res[i] = -INF;
			if (state[x]) op_t.add(x, 1);
			else op_t.add(x, -1);
		}
	}
	cdq(1, idx);
	up(i, 1, m) if (res[i] != -INF) cout << res[i] << '\n';
	
	return 0;
}

2025/8/1 20:38
加载中...