ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

20220502

2022-05-25 18:00:29  阅读:114  来源: 互联网

标签:cnt rs int void mx1 20220502 ls


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;
}

标签:cnt,rs,int,void,mx1,20220502,ls
来源: https://www.cnblogs.com/401rk8/p/16310193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有