2023.9.23

A

给出序列 \(\{a\}\),问有多少非空子集满足平均数 \(<\) 中位数

\(n\le 100\)\(a_i\le 800\).

可以 \(O(n^3V)\) 直接 DP。大家写的反悔背包常数很小。

#include<bits/stdc++.h>
#define ll long long
#define N 105
#define V 805
#define P 998244353
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
int read(){
	int x=0,w=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*w;
}
int n,v,a[N],s;
int f[N>>1][N*V],g[N>>1][N*V][2],sum[N>>1][N*V],ans;
void prework(){
	s=n*v;
	f[0][0]=g[0][0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=n/2;j;j--)
			for(int k=s;k>=a[i];k--)
				(g[j][k][0]+=g[j-1][k-a[i]][0])%=P;
}
void solve1(int i){
	if(!i)return;
	for(int j=n/2;j;j--)
		for(int k=s;k>=a[i];k--)
			(f[j][k]+=f[j-1][k-a[i]])%=P;
}
void solve2(int i){
	g[0][0][1]=1;
	for(int j=1;j<=n/2;j++)
		for(int k=0;k<=s;k++){
			if(k<a[i])g[j][k][1]=g[j][k][0];
			else g[j][k][1]=(g[j][k][0]-g[j-1][k-a[i]][1]+P)%P;
			g[j][k][0]=g[j][k][1];
			sum[j][k]=(sum[j][k-1]+g[j][k][0])%P;
		}
}
int main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	n=read(),v=read();
	for(int i=1;i<=n;i++)a[i]=read();
	sort(a+1,a+1+n);
	prework();
	for(int i=1;i<=n;i++){
		solve1(i-1),solve2(i);
		for(int j=1;j<=min(i-1,n-i);j++)
			for(int k=1,S=j*2*a[i];k<S;k++)
				(ans+=1ll*f[j][k]*sum[j][S-k-1]%P)%=P;
	}
	printf("%d\n",ans);
	
	return 0;
}

B

P8906 [USACO22DEC] Breakdown P

一个有向完全图(包括自环),进行 \(n^2\) 次删边,问每次删边后从 \(1\)\(n\) 的长为 \(k\) 的最短路长度,或指出不存在长为 \(k\)\(1\)\(n\) 的路径。

\(n\le 300\)\(2\le k\le 8\)\(1\le w_{i,j}\le 10^8\).

容易想到分层图,直接跑是 \(O(n^4k)\) 的。

考虑折半,对于所有点,记录从 \(1\) 开始经过 \(\lfloor\frac{k}{2}\rfloor\) 条边到达它,和从它开始经过 \(\lceil\frac{k}{2}\rceil\) 条边到达 \(n\) 的最短路。

先化删为加。添加一条边时,依次扫过分层图的每一层,若一个点被松弛过,将其所有出边松弛一遍。

时间复杂度 \(O(n^4k)\) 小常数不好卡。

#include<bits/stdc++.h>
#define ll long long
#define N 305
#define inf 1e12
using namespace std;
int read(){
	int x=0,w=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*w;
}
int n,k,_w[N][N];
int w[N][N],ans[N*N];
int X[N*N],Y[N*N];
struct Graph{
	int d[N][5];bool vs[N][5];
	int st,k;
	void init(int x,int p){
		memset(d,0x3f,sizeof(d));
		d[x][0]=0,st=x,k=p;
	}
	void upd(int x){
		memset(vs,0,sizeof(vs));
		for(int i=0;i<k;i++)vs[x][i]=1;
		for(int i=0;i<k;i++)
			for(int u=1;u<=n;u++)
				if(vs[u][i]){
					for(int v=1;v<=n;v++){
						if(d[v][i+1]>d[u][i]+w[u][v])
							vs[v][i+1]=true,d[v][i+1]=d[u][i]+w[u][v];
					}
				}
	}
}p1;
struct Graph2{
	int d[N][5];bool vs[N][5];
	int st,k;
	void init(int x,int p){
		memset(d,0x3f,sizeof(d));
		d[x][0]=0,st=x,k=p;
	}
	void upd(int x){
		memset(vs,0,sizeof(vs));
		for(int i=0;i<k;i++)vs[x][i]=true;
		for(int i=0;i<k;i++)
			for(int u=1;u<=n;u++)
				if(vs[u][i]){
					for(int v=1;v<=n;v++){
						if(d[v][i+1]>d[u][i]+w[v][u])
							vs[v][i+1]=true,d[v][i+1]=d[u][i]+w[v][u];
					}
				}
	}
}p2;
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			_w[i][j]=read(),w[i][j]=1e9;
	for(int i=1;i<=n*n;i++)
		X[i]=read(),Y[i]=read();
	p1.init(1,k>>1),p2.init(n,k+1>>1);
	for(int i=n*n;i;i--){
		ans[i]=2e9;
		for(int j=1;j<=n;j++)
			ans[i]=min(ans[i],p1.d[j][k>>1]+p2.d[j][k+1>>1]);
		if(ans[i]>=1e9)ans[i]=-1;
		w[X[i]][Y[i]]=_w[X[i]][Y[i]];
		p1.upd(X[i]),p2.upd(Y[i]);
	}
	for(int i=1;i<=n*n;i++)
		printf("%d\n",ans[i]);
	
	return 0;
}

C

P8476 「GLR-R3」惊蛰

构造一个单调不升的非负数列 \(\{b\}\),最小化

\[\sum_{i=1}^{n}f(b_i,a_i) \]

其中

\[f(x,y)=\begin{cases}x-y&x\ge y\\C&x<y\end{cases} \]

\(n\le 10^6\)\(0\le V\le 10^9\).

比较难的一集。没太贺懂。

#include<bits/stdc++.h>
#define ll long long
#define N 2000010
using namespace std;
int read(){
	int x=0,w=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*w;
}
int n,a[N],b[N],id[N];
ll dat[N<<2],tag1[N<<2],tag2[N<<2],C;
bool fl[N<<2];
#define ls p<<1
#define rs p<<1|1
void pushfl(int p){
	if(!fl[p])return;
	dat[ls]=dat[rs]=dat[p];
	tag1[ls]=tag1[rs]=tag2[ls]=tag2[rs]=0;
	fl[ls]=fl[rs]=1,fl[p]=0;
}
void pushdown(int p,int mid,int r){
	pushfl(p);
	pushfl(ls),pushfl(rs);
	if(tag1[p]){
		dat[ls]+=tag1[p],tag1[ls]+=tag1[p];
		dat[rs]+=tag1[p],tag1[rs]+=tag1[p];
		tag1[p]=0;
	}
	if(tag2[p]){
		dat[ls]+=b[mid]*tag2[p],tag2[ls]+=tag2[p];
		dat[rs]+=b[r]*tag2[p],tag2[rs]+=tag2[p];
		tag2[p]=0;
	}
}
void pushup(int p){
	dat[p]=min(dat[ls],dat[rs]);
}
ll val;
void update(int p,int l,int r,int x,ll v1,ll v2){
	int mid=(l+r)>>1;
	if(l!=r)pushdown(p,mid,r);
	if(r<=x){
		pushfl(p);
		dat[p]+=v1,tag1[p]+=v1;
		dat[p]+=b[r],tag2[p]++;
		if(r==x)val=dat[p];
		return;
	}
	if(l>x){
		pushfl(p);
		dat[p]+=v2,tag1[p]+=v2;
		return;
	}
	update(ls,l,mid,x,v1,v2);
	update(rs,mid+1,r,x,v1,v2);
	pushup(p);
}
bool modify(int p,int l,int r,int x,ll v){
	int mid=(l+r)>>1;
	if(l!=r)pushdown(p,mid,r);
	if(l>x){
		if(dat[p]>v){
			dat[p]=v,tag1[p]=tag2[p]=0;
			fl[p]=1;
			return 1;
		}
		if(l!=r){
			if(modify(ls,l,mid,x,v))
				modify(rs,mid+1,r,x,v);
		}
		return 0;
	}
	if(l==r)return 0;
	if(x<mid){
		if(modify(ls,l,mid,x,v))
			return modify(rs,mid+1,r,x,v);
		return 0;
	}
	return modify(rs,mid+1,r,x,v);
}
int main(){
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	n=read(),C=read();
	for(int i=1;i<=n;i++)
		a[i]=b[i]=read();
	sort(b+1,b+1+n);
	int len=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++){
		id[i]=lower_bound(b+1,b+1+len,a[i])-b;
		id[i]=len-id[i]+1;
	}
	reverse(b+1,b+1+len);
	for(int i=1;i<=n;i++){
		update(1,1,len,id[i],-a[i],C);
		modify(1,1,len,id[i],val);
	}
	printf("%lld\n",dat[1]);
	
	return 0;
}
posted @ 2023-09-23 16:01  SError  阅读(21)  评论(1编辑  收藏  举报