Examples

2022-8-9 #24 CF1408H & CF1696G & AGC043F

摆。

有同学给我推荐了音游,玩了一下,非常好玩啊!(所以这就是你不更博的理由吗

060 CF1408H Rainbow Triples

第一眼就可以想到一个网络流模型:将 \(0\) 向后面的 \(b_i\) 连边,\(b_i\) 向后面的 \(0\) 连边。问题在于怎么钦定哪些 \(0\) 连入,哪些 \(0\) 连出。

由于答案上界是 \(0\) 的数量 \(z\) 除二,可以钦定前一半 \(0\) 连入,后一半 \(0\) 连出,显然仍然正确。

对于一种颜色,我们找到这个颜色最靠前、最靠后的两个位置 \(u,v\),于是我们可以将连边刻画成 \(S\rightarrow c,c\rightarrow[1,\min(u,\lfloor\frac z2\rfloor)],c\rightarrow [\max(v,\lceil\frac z2\rceil)+1,z]\)

前缀后缀连边可以使用前缀和,令前一半的 \(0\) 从后往前连边,后一半的 \(0\) 从前往后连边,那么问题就变成了求这张图的最大流。

最大流转最小割,于是一个颜色不割,就要割对应的前缀和后缀所有点。

从后往前枚举前缀割了多长,用线段树维护每个后缀割的长度对应答案,复杂度 \(O(n\log n)\)

#include<stdio.h>
#include<vector>
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid (l+r>>1)
using namespace std;
const int maxn=500005,maxt=maxn<<2;
int T,n,z,ans;
int a[maxn],l[maxn],r[maxn],lazy[maxt],mn[maxt];
vector<int>v[maxn];
inline void pushup(int now){
	mn[now]=min(mn[lc(now)],mn[rc(now)]);
}
inline void getlazy(int now,int v){
	lazy[now]+=v,mn[now]+=v;
}
inline void pushdown(int now){
	if(lazy[now])
		getlazy(lc(now),lazy[now]),getlazy(rc(now),lazy[now]),lazy[now]=0;
}
void build(int l,int r,int now){
	lazy[now]=0;
	if(l==r){
		mn[now]=l+n;
		return ;
	}
	build(l,mid,lc(now)),build(mid+1,r,rc(now)),pushup(now);
}
void update(int l,int r,int now,int L,int R,int v){
	if(L<=l&&r<=R){
		getlazy(now,v);
		return ;
	}
	pushdown(now);
	if(L<=mid)
		update(l,mid,lc(now),L,R,v);
	if(mid<R)
		update(mid+1,r,rc(now),L,R,v);
	pushup(now);
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n),z=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]),z+=a[i]==0;
		for(int i=1;i<=n;i++)
			l[i]=r[i]=0;
		int now=0;
		for(int i=1;i<=n;i++){
			if(a[i]==0)
				now++;
			else if(now<=z/2)
				l[a[i]]=max(l[a[i]],now);
		}
		now=0;
		for(int i=n;i>=1;i--){
			if(a[i]==0)
				now++;
			else if(now<=z/2)
				r[a[i]]=max(r[a[i]],now);
		}
		build(0,z/2,1);
		for(int i=1;i<=n;i++)
			v[l[i]].push_back(r[i]);
		ans=1e9;
		for(int i=0;i<=z/2;i++){
			for(int j=0;j<v[i].size();j++)
				update(0,z/2,1,v[i][j],z/2,-1);
			v[i].clear();
			ans=min(ans,mn[1]+i);
		}
		printf("%d\n",min(z/2,ans));
	}
	return 0;
}

061 CF1696G Fishingprince Plays With Array Again

之后再写。

#include<stdio.h>
#include<string.h>
#include<iostream>
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid (l+r>>1)
using namespace std;
const int maxn=200005,maxt=maxn<<2; 
int n,m,x,y;
int a[maxn];
struct matrix{
	int len,wid;
	double a[4][4];
	matrix operator *(matrix p){
		matrix res;
		res.len=len,res.wid=p.wid;
		for(int i=1;i<=res.len;i++)
			for(int j=1;j<=res.wid;j++)
				res.a[i][j]=-1e18;
		for(int i=1;i<=len;i++)
			for(int j=1;j<=p.wid;j++)
				for(int k=1;k<=wid;k++)
					res.a[i][j]=max(res.a[i][j],a[i][k]+p.a[k][j]);
		return res;
	}
}st,t[maxt],trans;
inline void setval(int p,int now){
	t[now].len=t[now].wid=3,t[now].a[1][1]=0,t[now].a[2][2]=1.0*a[p]/x,t[now].a[3][3]=1.0*a[p]/(x+y);
}
inline void pushup(int now){
	t[now]=t[lc(now)]*trans*t[rc(now)];
}
void build(int l,int r,int now){
	if(l==r){
		setval(l,now);
		return ;
	}
	build(l,mid,lc(now)),build(mid+1,r,rc(now)),pushup(now);
}
void modify(int l,int r,int now,int p){
	if(l==r){
		setval(l,now);
		return ;
	}
	if(p<=mid)
		modify(l,mid,lc(now),p);
	else modify(mid+1,r,rc(now),p);
	pushup(now);
}
matrix query(int l,int r,int now,int L,int R){
	if(L<=l&&r<=R)
		return t[now];
	if(L<=mid&&mid<R)
		return query(l,mid,lc(now),L,R)*trans*query(mid+1,r,rc(now),L,R);
	if(L<=mid)
		return query(l,mid,lc(now),L,R);
	return query(mid+1,r,rc(now),L,R);
}
int main(){
	st.len=1,st.wid=3;
	trans.len=trans.wid=3,trans.a[2][2]=trans.a[2][3]=trans.a[3][2]=-1e18;//0 1/x 1/(x+y)
	scanf("%d%d%d%d",&n,&m,&x,&y);
	if(x<y)
		swap(x,y);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	build(1,n,1);
	for(int i=1,t,x,y;i<=m;i++){
		scanf("%d%d%d",&t,&x,&y);
		if(t==1)
			a[x]=y,modify(1,n,1,x);
		if(t==2){
			matrix res=st*query(1,n,1,x,y);
			double ans=0;
			for(int i=1;i<=3;i++)
				ans=max(ans,res.a[1][i]);
			printf("%.10lf\n",ans);
		}
	}
	return 0;
}

062 AGC043F Jewelry Box

之后再写。

#include<stdio.h>
#include<queue>
#include<vector>
#include<algorithm>
#define inf 1000000000000000000
#define INF 100000
using namespace std;
const int maxn=1005,maxm=10005;
int n,m,Q,e=1,flow,tot,s,t;
int start[maxn],to[maxm],then[maxm],limit[maxm],mn[maxn],vis[maxn],rec[maxn];
int K[maxn],sum[maxn];
long long cost;
long long dis[maxn],worth[maxm],res[3][maxn];
queue<int>q;
inline void add(int x,int y,int z,long long w){
    then[++e]=start[x],start[x]=e,to[e]=y,limit[e]=z,worth[e]=w;
}
inline void addedge(int x,int y,int z,long long w){
	add(x,y,z,w),add(y,x,0,-w);
}
int spfa(int s,int t){
	for(int i=1;i<=t;i++)
		dis[i]=inf,vis[i]=rec[i]=0;
	while(!q.empty())
		q.pop();
	dis[s]=0,vis[s]=1,mn[s]=INF,q.push(s);
	while(!q.empty()){
		int x=q.front();
		vis[x]=0,q.pop();
		for(int i=start[x];i;i=then[i]){
			int y=to[i];
			long long z=worth[i];
			if(limit[i]&&dis[y]>dis[x]+z){
				dis[y]=dis[x]+z,rec[y]=i,mn[y]=min(mn[x],limit[i]);
				if(vis[y]==0)
					q.push(y),vis[y]=1;
			}
		}
	}
	return rec[t]!=0;
}
void work(int s,int t){
	cost+=dis[t]*mn[t],flow+=mn[t];
	for(int i=t;i!=s;i=to[rec[i]^1])
		limit[rec[i]]-=mn[t],limit[rec[i]^1]+=mn[t];
}
struct jew{
	long long s,c;
	int p;
	bool operator <(const jew &t)const{
		return s<t.s||(s==t.s&&p<t.p);
	}
}w[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1,k;i<=n;i++){
		scanf("%d",&k),sum[i+1]=sum[i]+k,K[i]=k;
		for(int j=1;j<=k;j++)
			scanf("%lld%d%lld",&w[sum[i]+j].s,&w[sum[i]+j].p,&w[sum[i]+j].c);
		sort(w+sum[i]+1,w+sum[i]+k+1);
	}
	s=sum[n+1]+1,t=s+1;
	for(int i=1;i<=n;i++){
		int lst=s;
		for(int j=1;j<=K[i];j++){
			addedge(sum[i]+j,lst,INF,0),addedge(lst,sum[i]+j,INF,w[sum[i]+j].c);
			addedge(lst,sum[i]+j,w[sum[i]+j].p,0),lst=sum[i]+j;
		}
		addedge(sum[i]+K[i],t,INF,0),addedge(t,sum[i]+K[i],INF,0);
	}
	scanf("%d",&m);
	for(int i=1,x,y,z;i<=m;i++){
		scanf("%d%d%d",&x,&y,&z);
		for(int j=sum[x]+1;j<=sum[x]+K[x];j++){
			int p=lower_bound(w+sum[y]+1,w+sum[y]+K[y]+1,jew{w[j].s+z+1,0,0})-w;
			if(p==sum[y]+1)
				addedge(s,j,INF,0);
			else addedge(p-1,j,INF,0);
		}
	}
	while(spfa(s,t)){
		tot++,res[0][tot]=dis[t],work(s,t),res[1][tot]=flow,res[2][tot]=cost;
		if(flow>=INF)
			break;
	}
	scanf("%d",&Q);
	while(Q--){
		long long x;
		scanf("%lld",&x);
		int p=(lower_bound(res[0]+1,res[0]+1+tot,x)-res[0]);
		if(p>tot)
			puts("-1");
		else printf("%lld\n",x*res[1][p-1]-res[2][p-1]);
	}
	return 0;
}
posted @ 2022-08-09 15:13  xiaoziyao  阅读(101)  评论(0编辑  收藏  举报