萌新刚学数据结构, 求调线段树
查看原帖
萌新刚学数据结构, 求调线段树
374500
AtomAlpaca楼主2023/7/3 18:20

rt, 这几天一直在写这题, 一共写了五棵, 这颗是表现最好的, 能过掉样例(subtask0) 和后面零星几个数据点, 其他数据点全部 WA

#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::vector;

typedef long long ll;
typedef vector<ll> V;
typedef vector<ll>::iterator iter;

const ll MOD = 1e9 + 7;
const ll MAX = 1e5 + 5;

ll n, m, l, r, op, x;
ll num[MAX], opr[MAX];

ll qp(ll a, ll x)
{
	ll res = 1;
	while (x)
	{
		if (x & 1) { res = res * a % MOD; }
		a = a * a % MOD; x >>= 1;
	}
	return res % MOD;
}

struct T
{
	bool at, mt, op;
	int lv, rv;
	int * c; V v;
	ll ln, sq;
	ll sm, ml, lm, rm, lc, rc, vl, ag;
	void clear()
	{
		for (int i = 1; i <= sq; ++i) { c[i] = 0; } v.clear();
	}

	void asgadd()
	{
		vl = sm % MOD; op = 0; lc = rc = 1; lm = lv, rm = rv;
		clear(); c[1] += ln;
		at = true; mt = false;
	}

	void asgmul()
	{
		vl = ml % MOD; op = 1; lc = rc = ln; lm = rm = ml % MOD;
		clear(); if (ln <= sq) { ++c[ln]; } else { v.push_back(ln); }
		mt = true; at = false;
	}

	void asg(ll v)
	{
		v %= MOD; lv = rv = v; vl = 0;
		lm = qp(v, lc); rm = qp(v, rc); ml = qp(v, ln); sm = v * ln % MOD;
		ll now = v;
		for (int i = 1; i <= sq; ++i, now = now * v % MOD)
		{
			if (c[i])
			{	
				vl = (vl + 1ll * now * c[i] % MOD) % MOD;
			}
		}
		for (int i : this -> v)
		{
			vl = (vl + qp(v, i)) % MOD; 
		}
		ag = v;
	}

	void merge(T & l, T & r)
	{
		sm = (l.sm + r.sm) % MOD;
		ml = 1ll * l.ml * r.ml % MOD;
		lv = l.lv, rv = r.rv;
		op = r.op;
		lm = l.lm % MOD, rm = r.rm % MOD, lc = l.lc, rc = r.rc;
		if (l.op and l.lc == l.ln) { lc = l.ln + r.lc; lm = 1ll * l.ml * r.lm % MOD; }
		if (l.op and r.rc == r.ln) { rc = r.ln + l.rc; rm = 1ll * r.ml * l.rm % MOD; }
		vl = (l.vl + r.vl) % MOD;
		if (l.op)
		{
			vl = ((((l.vl + r.vl) % MOD + 1ll * l.rm * r.lm % MOD) % MOD - (l.rm + r.lm) % MOD) % MOD + MOD) % MOD;
		}
		clear();
		for (int i = 1; i <= l.sq; ++i) { c[i] += l.c[i]; }
		for (int i = 1; i <= r.sq; ++i) { c[i] += r.c[i]; }
		int i1 = 0, i2 = 0, e1 = l.v.size(), e2 = r.v.size();
		while (i1 < e1 and i2 < e2)
		{
			if (l.v[i1] < r.v[i2])
			{
				if (l.v[i1] <= sq) { c[l.v[i1]]++; }
				else { v.push_back(l.v[i1]); }
				++i1;
			}
			else
			{
				if (r.v[i2] <= sq) { c[r.v[i2]]++; }
				else { v.push_back(r.v[i2]); }
				++i2;
			}
		}
		while (i1 < e1)
		{
			if (l.v[i1] <= sq) { c[l.v[i1]]++; }
			else { v.push_back(l.v[i1]); }
			++i1;
		}
		while (i2 < e2)
		{
			if (r.v[i2] <= sq) { c[r.v[i2]]++; }
			else { v.push_back(r.v[i2]); }
			++i2;
		}	
		if (l.op)
		{
			if (l.rc <= sq) { --c[l.rc]; }
			else { iter i = lower_bound(v.begin(), v.end(), l.rc); v.erase(i); }
			if (r.lc <= sq) { --c[r.lc]; }
			else { iter i = lower_bound(v.begin(), v.end(), r.lc); v.erase(i); }
			if (l.rc + r.lc <= sq) { ++c[l.rc + r.lc]; }
			else { iter i = lower_bound(v.begin(), v.end(), l.rc + r.lc); v.insert(i, l.rc + r.lc); }
		}
	}
	
	void pushdown(T & l, T & r)
	{
		if (ag) { l.asg(ag); r.asg(ag); ag = 0; } 
		if (at) { l.asgadd(); r.asgadd(); at = false; }
		if (mt) { l.asgmul(); r.asgmul(); mt = false; }
	}
} a[MAX << 2 | 1];

struct A
{
	ll lm, rm, lc, rc, vl, ln, op;
};

A merge(A l, A r)
{
	A x;
	x.op = r.op; x.ln = l.ln + r.ln;
	x.lc = l.lc; x.rc = r.rc;
	x.lm = l.lm; x.rm = r.rm;
	if (l.op and l.lc == l.ln) { x.lc = l.ln + r.lc; x.lm = 1ll * l.lm * r.lm; }
	if (l.op and r.rc == r.ln) { x.rc = r.ln + l.rc; x.rm = 1ll * r.rm * l.rm; }
	x.vl = (l.vl + r.vl) % MOD;
	if (l.op)
	{
		x.vl = (((x.vl + 1ll * l.rm * r.lm) % MOD - (l.rm + r.lm) % MOD) % MOD + MOD) % MOD;
	}
	return x;
}

A query(int l, int r, int s, int t, int x)
{
	if (l >= s and r <= t) { return {a[x].lm, a[x].rm, a[x].lc, a[x].rc, a[x].vl % MOD, a[x].ln, a[x].op}; }
	a[x].pushdown(a[x << 1], a[x << 1 | 1]);
	int k = l + ((r - l) >> 1);
	if (k >= t) { return query(l, k, s, t, x << 1); }
	else if (k <  s) { return query(k + 1, r, s, t, x << 1 | 1); }
	else { return merge(query(l, k, s, t, x << 1), query(k + 1, r, s, t, x << 1 | 1)); }
}

void build(int l, int r, int x)
{
	a[x].ln = r - l + 1; a[x].sq = sqrt(a[x].ln); a[x].c = new int [a[x].sq + 3]();
	if (l == r)
	{
		a[x].vl = a[x].lv = a[x].rv = a[x].lm = a[x].rm = a[x].sm = a[x].ml = num[l];
		a[x].op = opr[l]; a[x].lc = a[x].rc = 1; a[x].c[1] = 1;
		return ;
	}
	int k = l + ((r - l) >> 1);
	build(l, k, x << 1); build(k + 1, r, x << 1 | 1);
	a[x].merge(a[x << 1], a[x << 1 | 1]);
}

void asg(int l, int r, int s, int t, ll v, int x)
{
	if (l >= s and r <= t) { a[x].asg(v); return ; }
	a[x].pushdown(a[x << 1], a[x << 1 | 1]);
	int k = l + ((r - l) >> 1);
	if (k >= s) { asg(l, k, s, t, v, x << 1); }
	if (k <  t) { asg(k + 1, r, s, t, v, x << 1 | 1); }
	a[x].merge(a[x << 1], a[x << 1 | 1]);
}

void asgadd(int l, int r, int s, int t, int x)
{
	if (l >= s and r <= t) { a[x].asgadd(); return ; }
	a[x].pushdown(a[x << 1], a[x << 1 | 1]);
	int k = l + ((r - l) >> 1);
	if (k >= s) { asgadd(l, k, s, t, x << 1); }
	if (k <  t) { asgadd(k + 1, r, s, t, x << 1 | 1); }
	a[x].merge(a[x << 1], a[x << 1 | 1]);
}

void asgmul(int l, int r, int s, int t, int x)
{
	if (l >= s and r <= t) { a[x].asgmul(); return ; }
	a[x].pushdown(a[x << 1], a[x << 1 | 1]);
	int k = l + ((r - l) >> 1);
	if (k >= s) { asgmul(l, k, s, t, x << 1); }
	if (k <  t) { asgmul(k + 1, r, s, t, x << 1 | 1); }
	a[x].merge(a[x << 1], a[x << 1 | 1]);
}


int main()
{
	// cin.tie(NULL); cout.tie(NULL); std::ios::sync_with_stdio(false);
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) { cin >> num[i]; num[i] %= MOD; }
	for (int i = 1; i <  n; ++i) { cin >> opr[i]; }
	build(1, n, 1);
	while (m--)
	{
		cin >> op >> l >> r;
		if (op != 3) { cin >> x; }
		if (op == 1) { asg(1, n, l, r, x % MOD, 1); }
		else if (op == 2)
		{
			if (x == 0) { asgadd(1, n, l, r, 1); }
			else { asgmul(1, n, l, r, 1); }
		}
		else { cout << query(1, n, l, r, 1).vl % MOD << '\n'; }
	}
}

2023/7/3 18:20
加载中...