0225模擬賽

T1

在這裏插入圖片描述
直接按照定義推式子,就可以用矩陣加速優化。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 998244353;
int len;
struct mat {
	int a[3][3];
	mat(){memset(a,0,sizeof a);}
	inline mat operator *(const mat &o)const {
		mat re;
		for(int i = 0; i < len; ++i)
			for(int j = 0; j < len; ++j)
				for(int k = 0; k < len; ++k)
					re.a[i][j] = (re.a[i][j] + 1ll * a[i][k] * o.a[k][j]) % mod;
		return re;
	}
	inline mat operator ^(LL b) const {
		mat re, A = (*this);
		for(int i = 0; i < len; ++i) re.a[i][i] = 1;
		while(b) {
			if(b&1) re = re * A;
			A = A * A; b >>= 1;
		}
		return re;
	}
}tr, ans;
inline int qpow(int a, LL b) {
	int re = 1;
	while(b) {
		if(b&1) re = 1ll * re * a % mod;
		a = 1ll * a * a % mod; b >>= 1;
	}
	return re;
}
LL n; int k;
void solve0() { printf("%d\n", qpow(2, n-1)); }
void solve1() {
	len = 2;
	tr.a[0][0] = 1; tr.a[0][1] = 1;
	tr.a[1][0] = 1; tr.a[1][1] = 2;
	ans.a[0][0] = 1;
	ans.a[1][0] = 2;
	if(n == 1) printf("%d\n", 1);
	else {
		ans = (tr ^ (n-1)) * ans;
		printf("%d\n", ans.a[0][0]);
	}
}
void solve2() {
	len = 3;
	tr.a[0][0] = 1; tr.a[0][1] = 2; tr.a[0][2] = 1;
	tr.a[1][0] = 0; tr.a[1][1] = 1; tr.a[1][2] = 1;
	tr.a[2][0] = 1; tr.a[2][1] = 2; tr.a[2][2] = 2;
	ans.a[0][0] = 1;
	ans.a[1][0] = 1;
	ans.a[2][0] = 2;
	if(n == 1) printf("%d\n", 1);
	else {
		ans = (tr ^ (n-1)) * ans;
		printf("%d\n", ans.a[0][0]);
	}
}
int main () {
	freopen("generate.in", "r", stdin);
	freopen("generate.out", "w", stdout);
	scanf("%lld%d", &n, &k);
	if(k == 0) solve0();
	else if(k == 1) solve1();
	else if(k == 2) solve2();
}

T2

在這裏插入圖片描述
在這裏插入圖片描述
線段樹查詢回傳值時沒開longlong。爆成60分。

#include<bits/stdc++.h>
using namespace std;
inline void read(int &x) {
	char ch; while(!isdigit(ch=getchar()));
	for(x=ch-'0'; isdigit(ch=getchar()); x=x*10+ch-'0');
}
typedef long long LL;
const int MAXN = 100005;
const int MAXM = 200005;
int n, m, a[MAXN], lst[32], pos[MAXN][32];
struct node {
	int l, r, id;
	inline bool operator <(const node &o)const {
		return l > o.l;
	}
};
vector<node>q[32];
LL ans[MAXM];
int lz[MAXN<<2];
LL sum[MAXN<<2];
void build(int i, int l, int r) {
	lz[i] = sum[i] = 0;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(i<<1, l, mid);
	build(i<<1|1, mid+1, r);
}

inline void pd(int i, int l, int mid, int r) {
	if(lz[i]) {
		lz[i<<1] += lz[i], lz[i<<1|1] += lz[i];
		sum[i<<1] += 1ll * (mid-l+1) * lz[i];
		sum[i<<1|1] += 1ll * (r-mid) * lz[i];
		lz[i] = 0;
	}
}
void add(int i, int l, int r, int x, int y) {
	if(x == l && r == y) {
		lz[i]++;
		sum[i] += r-l+1;
		return;
	}
	int mid = (l + r) >> 1;
	pd(i, l, mid, r);
	if(y <= mid) add(i<<1, l, mid, x, y);
	else if(x > mid) add(i<<1|1, mid+1, r, x, y);
	else {
		add(i<<1, l, mid, x, mid);
		add(i<<1|1, mid+1, r, mid+1, y);
	}
	sum[i] = sum[i<<1] + sum[i<<1|1];
}
LL query(int i, int l, int r, int x) {
	if(r <= x) return sum[i];
	int mid = (l + r) >> 1; LL re = 0;
	pd(i, l, mid, r);
	if(x > mid) re += query(i<<1|1, mid+1, r, x);
	return re + query(i<<1, l, mid, x);
}
int main () {
	freopen("sequence.in", "r", stdin);
	freopen("sequence.out", "w", stdout);
	read(n), read(m);
	for(int i = 0; i < 30; ++i) lst[i] = n+1;
	for(int i = 1; i <= n; ++i) read(a[i]);
	for(int i = n; i >= 1; --i) {
		for(int j = 0; j < 30; ++j) {
			if(!(a[i]>>j&1)) lst[j] = i;
			pos[i][j+1] = lst[j];
		}
		sort(pos[i] + 1, pos[i] + 30 + 1);
		pos[i][0] = i; pos[i][31] = n+1;
	}
	for(int i = 1, l, r, k; i <= m; ++i) {
		read(l), read(r), read(k);
		q[k].push_back((node){l, r, i});
	}
	for(int k = 0; k <= 30; ++k) if(q[k].size()) {
		build(1, 1, n);
		sort(q[k].begin(), q[k].end());
		int siz = q[k].size(), j = n;
		for(int i = 0, l, r, L, R; i < siz; ++i) {
			l = q[k][i].l, r = q[k][i].r;
			while(l <= j) {
				L = pos[j][30-k], R = pos[j][30-k+1] - 1;
				if(L <= R) add(1, 1, n, L, R);
				--j;
			}
			ans[q[k][i].id] += query(1, 1, n, r);
		}
	}
	for(int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
}

T3

就是[HNOI2015]接水果的強制在線版本。
具體做法是把離線數據結構換成樹套樹或者kd樹。

#include<bits/stdc++.h>
const int MAXN = 100005;
const int MAXM = 800005;
const int LOG = 16;
using namespace std;
int n, m, dep[MAXN], f[MAXN][LOG+1], in[MAXN], out[MAXN], tmr;
int fir[MAXN], nxt[MAXN<<1], to[MAXN<<1], cnt;
inline void line(int x, int y) { nxt[++cnt] = fir[x], fir[x] = cnt, to[cnt]= y; }
void dfs(int u, int ff){
	in[u] = ++tmr, f[u][0] = ff, dep[u] = dep[ff] + 1;
	for(int i = fir[u]; i; i = nxt[i]) if(to[i] != ff) dfs(to[i], u);
	out[u] = tmr;
}
inline int ser(int u, int v){
	for(int i = 0, d = dep[u]-dep[v]-1; d; d>>=1, ++i) if(d&1) u = f[u][i];
	return u;
}
inline int lca(int u, int v){
	if(dep[u] < dep[v]) swap(u, v);
	for(int i = 0, d = dep[u]-dep[v]; d; d>>=1, ++i) if(d&1) u = f[u][i];
	if(u == v) return u;
	for(int i = LOG; i >= 0; i--) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
	return f[u][0];
}
struct node{
	int d[2], mn[2], mx[2], ch[2], siz, s, v, nd;
	void upd(node *t){
		mn[0] = mx[0] = d[0], mn[1] = mx[1] = d[1], s = v, siz = 1;
		for(int i = 0; i < 2; i++) if(ch[i]){
			siz += t[ch[i]].siz, s += t[ch[i]].s;
			for(int j = 0; j < 2; j++)
				mn[j] = min(mn[j], t[ch[i]].mn[j]),
				mx[j] = max(mx[j], t[ch[i]].mx[j]);
		}
	}
}t[MAXM];
int rt, sz, id[MAXM], *tmp, X, Y, ans;
template<int D>bool cmp(int i,int j){return t[i].d[D] < t[j].d[D];}
bool (*fun[2])(int, int) = {cmp<0>, cmp<1>};
void build(int &i, int l, int r, int D){
	if(l > r) return (void)(i=0);
	int o = (l+r)>>1; nth_element(id + l, id + o, id + r + 1, fun[D]), i = id[o];
	build(t[i].ch[0], l, o-1, D^1), build(t[i].ch[1], o+1, r, D^1);
	t[i].upd(t), t[i].nd=D;
}
void ins(int &i, int x, int D){
	if(!i) { t[i=x].upd(t), t[i].nd = D; return; }
	ins(t[i].ch[fun[D](i,x)], x, D^1), t[i].upd(t);
	if(t[i].siz*0.75 < max(t[t[i].ch[0]].siz, t[t[i].ch[1]].siz)) tmp = &i;
}
void biang(int i){ if(!i) return; id[++*id] = i, biang(t[i].ch[0]), biang(t[i].ch[1]); }
void qry(int i){
	if(!i || t[i].mn[0] > X || t[i].mn[1] > Y) return;
	if(t[i].mx[0] <= X && t[i].mx[1] <= Y) { ans += t[i].s; return; }
	if(t[i].d[0] <= X && t[i].d[1] <= Y) ans += t[i].v;
	qry(t[i].ch[0]), qry(t[i].ch[1]);
}
inline void AP(int x, int y, int v){
	t[++sz].d[0] = x, t[sz].d[1] = y, t[sz].v = v, tmp = 0, ins(rt, sz, 0);
	if(tmp) id[0] = 0, biang(*tmp), build(*tmp, 1, id[0], t[*tmp].nd);
}
inline void AM(int a, int b, int c, int d){
	AP(a, c, 1);
	if(d<n) AP(a, d+1, -1);
	if(b<n) AP(b+1, c, -1);
	if(d<n&&b<n) AP(b+1, d+1, 1);
}
int arr[MAXN], val[MAXN];
inline int qsum(int i){int s=0;for(; i; i-=i&-i) s += arr[i]; return s; }
inline void upd(int i, int d){for(; i<=n; i+=i&-i) arr[i] += d; }
int main() {
	freopen("water.in", "r", stdin);
	freopen("water.out", "w", stdout);
	int x, y;
	char op;
	scanf("%d%d", &n, &m);
	for(int i = 1; i < n; i++)
		scanf("%d%d", &x,&y),
		line(x, y),
		line(y, x);
	dfs(1,0);
	for(int j = 1;j <= LOG; j++)
		for(int i = 1; i <= n; i++)
			f[i][j] = f[f[i][j-1]][j-1];
	while(m--) {
		while(!isalpha(op = getchar()));
		scanf("%d%d", &x, &y), x ^= ans, y ^= ans; if(in[x] > in[y]) swap(x, y);
		if(op == 'A') {
			if(x == y) {
				val[x]++,
				upd(in[x], 1),
				upd(out[x]+1, -1);
				continue;
			}
			if(in[x] <= in[y] && out[y] <= out[x]){
				int z = ser(y, x);
				AM(1, in[z]-1, in[y], out[y]);
				if(out[z] < n)
					AM(in[y], out[y], out[z]+1, n);
			}
			else
				AM(in[x], out[x], in[y], out[y]);
		}
		else{
			X = in[x], Y = in[y];
			int z = lca(x,y);
			ans = qsum(X) + qsum(Y) - 2*qsum(in[z]) + val[z],
			qry(rt);
			printf("%d\n",ans);
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章