20220502

tot: 140 (280)
rk: 10/28


a

100pts

不存在 \(0\) 的话区间合法 \(\iff\) 区间和为偶数,线段树维护区间和分别为奇偶的左端点有多少个即可

\(0\) 相当于分成了若干段,维护下最后一个合法段的左端点即可

考场代码
const int N = 5e5+5;
int n,m,a[N];
bool s[N];
vector<Pii> q[N];
LL ans[N];

#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
#define root int u=1,int l=1,int r=n
#define lson ls,l,mid
#define rson rs,mid+1,r
struct { int cnt0,cnt1,sum0,sum1; LL res; bool flip; } t[N*4];
void up(int u) {
	t[u].sum0 = t[ls].sum0+t[rs].sum0, t[u].sum1 = t[ls].sum1+t[rs].sum1,
	t[u].res = t[ls].res + t[rs].res;
}
void flip(int u)
	{ swap(t[u].cnt0,t[u].cnt1), swap(t[u].sum0,t[u].sum1), t[u].flip ^= 1; }
void down_cnt(int u,int cnt0,int cnt1) {
	t[u].res += (LL)cnt0 * t[u].sum0 + (LL)cnt1 * t[u].sum1,
	t[u].cnt0 += cnt0, t[u].cnt1 += cnt1;
}
void down(int u) {
	if( t[u].flip ) flip(ls), flip(rs), t[u].flip = 0;
	down_cnt(ls,t[u].cnt0,t[u].cnt1), down_cnt(rs,t[u].cnt0,t[u].cnt1),
	t[u].cnt0 = t[u].cnt1 = 0;
}
void bld(root) { t[u].sum0 = r-l+1; if( l == r ) return; bld(lson), bld(rson); }
void mdf(int qr,root) {
	if( qr < l ) return;
	if( r <= qr ) return flip(u);
	down(u), mdf(qr,lson), mdf(qr,rson), up(u);
}
void add(int ql,int qr,root) {
	if( qr < l || r < ql ) return;
	if( ql <= l && r <= qr ) return down_cnt(u,1,0);
	down(u), add(ql,qr,lson), add(ql,qr,rson), up(u);
}
LL qry(int ql,root) {
	if( r < ql ) return 0;
	if( ql <= l ) return t[u].res;
	return down(u), qry(ql,lson) + qry(ql,rson);
}

signed main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout);
	io>>n>>m; For(i,1,n) io>>a[i], s[i] = s[i-1] ^ (a[i]&1);
	For(i,1,m, l,r) io>>l>>r, q[r].pb(i,l);
	bld(); For(i,1,n, lst = 0, l = 1) {
		if( a[i] & 1 ) mdf(i);
		add(lst&&(s[lst]^s[i])?lst:l,i);
		for(auto j : q[i]) ans[j.fi] = qry(j.se);
		if( !a[i] ) {
			if( s[lst]^s[i] ) l = lst;
			lst = i;
		}
	}
	For(i,1,m) io<<ans[i]<<endl;
	return 0;
}

b

20pts, max = 100pts

由于 \(l1,r1\) 随机,所以按 \(l1\) 排序后 \(r1\) 的 LIS 长度期望为 \(\sqrt{q}\),可以把询问分成 \(\sqrt{q}\) 组,每次 \(l1\) 递减,\(r1\) 递增,吉老师线段树维护即可。时间复杂度 \(O(n\sqrt{q}\log n)\)

code
const int N = 1.5e4+5, Q = 1e5+5;
int n,m,qn,ind,a[N],le[N],ri[N],val[N],ed[Q],nxt[Q];
LL ans[Q];
bool bg[Q];
struct Node { int id,l,r,ll,rr; } q[Q];

#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct {
	struct { int mx1,mx2,cnt,add; LL sum; } t[N*4];
	void up(int u) {
		t[u].sum = t[ls].sum + t[rs].sum,
		t[u].mx1 = max(t[ls].mx1,t[rs].mx1), t[u].mx2 = t[u].cnt = 0;
		if( t[u].mx1 == t[ls].mx1 ) t[u].cnt += t[ls].cnt, ckmax(t[u].mx2,t[ls].mx2);
		else ckmax(t[u].mx2,t[ls].mx1);
		if( t[u].mx1 == t[rs].mx1 ) t[u].cnt += t[rs].cnt, ckmax(t[u].mx2,t[rs].mx2);
		else ckmax(t[u].mx2,t[rs].mx1);
	}
	void down(int u,int x)
		{ t[u].mx1 += x, t[u].sum += (LL)x * t[u].cnt, t[u].add += x; }
	void down(int u) { if( t[u].add ) {
		int mx = max(t[ls].mx1,t[rs].mx1);
		if( mx == t[ls].mx1 ) down(ls,t[u].add);
		if( mx == t[rs].mx1 ) down(rs,t[u].add);
		t[u].add = 0;
	}}
	void bld(int u=1,int l=1,int r=n) {
		t[u].add = 0;
		if( l == r ) return t[u].mx1 = t[u].sum = a[l], t[u].cnt = 1, void();
		bld(ls,l,mid), bld(rs,mid+1,r), up(u);
	}
	void mdf(int ql,int qr,int x,int u=1,int l=1,int r=n) {
		if( qr < l || r < ql || x >= t[u].mx1 ) return;
		if( ql <= l && r <= qr && x > t[u].mx2 ) return down(u,x-t[u].mx1);
		down(u), mdf(ql,qr,x,ls,l,mid), mdf(ql,qr,x,rs,mid+1,r), up(u);
	}
	LL qry(int ql,int qr,int u=1,int l=1,int r=n) {
		if( qr < l || r < ql ) return 0;
		if( ql <= l && r <= qr ) return t[u].sum;
		return down(u), qry(ql,qr,ls,l,mid)+qry(ql,qr,rs,mid+1,r);
	}
} seg;

signed main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout);
	io>>n>>m>>qn; For(i,1,n) io>>a[i]; For(i,1,m) io>>le[i]>>ri[i]>>val[i];
	For(i,1,qn) io>>q[i].l>>q[i].r>>q[i].ll>>q[i].rr, q[i].id = i;
	sort(q+1,q+qn+1,[](const Node &x,const Node &y){return x.l>y.l;});
	For(i,1,qn) {
		int k = 0;
		For(j,1,ind) if( q[ed[j]].r <= q[i].r && q[ed[j]].r > q[ed[k]].r ) k = j;
		if( k ) nxt[ed[k]] = i, ed[k] = i;
		else bg[i] = 1, ed[++ind] = i;
	}
	For(i,1,qn) if( bg[i] ) {
		seg.bld();
		for(int l = q[i].l, r = q[i].l-1, j = i; j; j = nxt[j]) {
			while( l > q[j].l ) --l, seg.mdf(le[l],ri[l],val[l]);
			while( r < q[j].r ) ++r, seg.mdf(le[r],ri[r],val[r]);
			ans[q[j].id] = seg.qry(q[j].ll,q[j].rr);
		}
	}
	For(i,1,qn) io<<ans[i]<<endl;
	return 0;
}

c

20pts, max = 100pts

考虑暴力 FWT:给每个数开一个桶并做 FWT,选 \(m\) 个桶对位乘再求所有方案的和,最后 iFWT 回去

发现点值 \(\in\{1,-1\}\) 且每个位置独立,对于有 \(x\)\(-1\) 位置,和为 \(\sum_{i=0}^{x}(-1)^{x}{x\choose i}{n-x\choose m-i}\),拆成阶乘形式可以 NTT 计算。对所有 \(a_i\) 形成的桶 FWT 可以得到每个位置点值的和,从而解出 \(x\)

code
#define a(i) (*this)[i]
namespace Poly {
const int N = 1<<17, g = 3, ivg = (mod+1)/3;
int r[N]; LL w[N];
struct poly : vector<LL> {
	void ntt(int n,bool op) {
		resize(n);
		Rep(i,0,n) if( i < (r[i]=r[i>>1]>>1|(i&1?n>>1:0)) )
			a(i)^=a(r[i])^=a(i)^=a(r[i]);
		for(int i = 1; i < n; i <<= 1) {
			w[0] = 1, w[1] = Pow(op?g:ivg,mod/i/2);
			Rep(j,2,i) w[j] = w[j-1] * w[1] %mod;
			for(int j = 0; j < n; j += i<<1) Rep(k,0,i) {
				LL x = a(j+k), y = a(j+k+i) * w[k] %mod;
				a(j+k) = Mod(x+y), a(j+k+i) = Mod(x-y);
			}
		}
		if( !op ) Rep(i,0,n, inv = Pow(n)) (a(i) *= inv) %=mod;
	}
	poly operator * (poly b) const {
		poly a = *this;
		int n = 1; while( n < sz(a)+sz(b) ) n <<= 1;
		a.ntt(n,1), b.ntt(n,1); Rep(i,0,n) (a[i] *= b[i]) %=mod; a.ntt(n,0);
		return a;
	}
};
} using Poly::poly;
#undef a

const int N = 1<<17;
int n,m,X;
LL fac[N],ivf[N],a[N];
poly f,g;

void fwt(LL f[]) {
	for(int i = 1; i < X; i <<= 1) for(int j = 0; j < X; j += i<<1) Rep(k,0,i) {
		LL x = f[j+k], y = f[j+k+i];
		f[j+k] = x+y, f[j+k+i] = x-y;
	}
}
void ifwt(LL f[]) {
	for(int i = 1; i < X; i <<= 1) for(int j = 0; j < X; j += i<<1) Rep(k,0,i) {
		LL x = f[j+k], y = f[j+k+i];
		f[j+k] = (x+y) * iv2 %mod, f[j+k+i] = Mod(x-y) * iv2 %mod;
	}
}

signed main() { freopen("c.in","r",stdin); freopen("c.out","w",stdout);
	io>>n>>m>>X; For(i,1,n, x) io>>x, ++a[x];
	ivf[0] = ivf[1] = fac[0] = fac[1] = 1;
	For(i,2,n) fac[i] = fac[i-1] * i %mod, ivf[i] = (mod-mod/i) * ivf[mod%i] %mod;
	For(i,2,n) (ivf[i] *= ivf[i-1]) %=mod;
	fwt(a);
	f.resize(m+1); For(i,0,m) {
		f[i] = ivf[i] * ivf[m-i] %mod;
		if( i & 1 ) f[i] = Mod(-f[i]);
	}
	g.resize(n-m+1); For(i,0,n-m) g[i] = ivf[i] * ivf[n-m-i] %mod;
	f = f * g; For(i,0,n) (f[i] *= fac[i] * fac[n-i] %mod) %=mod;
	Rep(i,0,X) a[i] = f[(n-a[i])/2];
	ifwt(a);
	Rep(i,0,X) io<<a[i]<<' ';
	return 0;
}
posted @ 2022-05-25 17:54  401rk8  阅读(44)  评论(1编辑  收藏  举报