10.22

CSP前夕

模拟赛

由于没有发很强的大样例,加上出现的一些令人匪夷所思的问题,做的不好
然而B,C两题我是会做的

总结错因:
C:大样例没有发现我的问题,但程序背包那一行的循环有点问题,居然还有50分,可见数据较弱
B:本机下评测完全可过,赛后经过一番审查发现问题出在getline(cin,str),在洛谷上也AC不了,可见确实是个值得重视的问题。getline似乎会莫名其妙地输进来一些不该输进来的东西而不会将它们吃掉,例如换行符空格等,但当你判if(str=="\n"||str==" ")像这样的时候却还是有问题,需要改成if(str.length()<3),很让人不解,为什么它会输进来这些“乱码”?需要注意,今天解决!

我的B,C题解:

B
容易发现这n个点之间不会形成环。显然可以根据后面输入的“加边操作”建一棵树出来,即对于每一个加边操作u v w,连接u v(先不管w)。需要注意的是,这个其实不是一棵准确意义上的树,因为可能不连通。考虑树链剖分(不连通的树不影响树剖)。由于是链上的询问,所以每一个节点的值表示他与他的父亲相连的那一条边的当前权值。最开始把每一条边的权值都赋为 \(-\infty\),为什么,因为这样保证在我们查询的时候但凡起始点目前不连通(但属于一个我们构造的树的连通块内),则查到的路径和一定<0,(不合法)。再离线依次处理每一次操作,u v w就是在u,v中深度较大的那个的值上加w,属于单点修改,无需树剖;u v就是查u到v的路径上的和,如果小于零,或者u,v自己都不在一个连通块内,那就输出-1,否则输出路径和。

C
题目就是要我们划分为两个点集S,T,使S和S中的边、T和T中的边都构成的是完全图。
很自然地想到有解的充要条件是图的反图是二分图!因此只需用最基础的染色法判定是不是二分图,如果不是直接-1.下面讨论有解情况。
由于图不一定联通,我们对每一个连通块染色,假如连通块有标号的话,那么第i个连通块染成i和-i两种颜色。接着我们用桶统计每一种颜色的出现次数。
你可以自己推一下,你会发现当划分成的两个部分点的个数相近(都接近于n/2)时答案最优。
于是就转化成了有一个容量为n/2(整除)的背包,一共2t个物品,编号为1,-1,2,-2,...(t是连通块数),第i物品的体积和价值都是\(bk[i]\)(bk[i]指颜色i的出现次数),第i和-i个物品必须选且仅选其一,问背包最大价值。剩下的注意不要出岔子就好。

Bsubmission
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n,q,tot,rt,dep[N],dfn[N],top[N],son[N],fa[N],siz[N],bel[N];
ll edg[N],t[N<<2];
vector<int>G[N];
string r;
struct QR {
	int o[3];
}a[N];
void dfs(int x,int p){
	dep[x]=dep[p]+1;siz[x]=1;fa[x]=p;bel[x]=rt;
	for(int i=0;i<G[x].size();i++){
		int y=G[x][i];
		if(y^p){
			dfs(y,x);
			siz[x]+=siz[y];
			if(siz[y]>siz[son[x]])son[x]=y;
		}
	} 
}
void dfs2(int x,int p,int tp){
	top[x]=tp;dfn[x]=++tot;
	if(son[x])dfs2(son[x],x,tp);
	for(int i=0;i<G[x].size();i++){
		int y=G[x][i];
		if((y^p)&&(y^son[x]))dfs2(y,x,y);
	}
}
void pushup(int k){
	t[k]=t[k<<1]+t[k<<1|1];
} 
void bld(int l,int r,int k){
	if(l==r){t[k]=-1e10;return;}
	int mid=l+r>>1;bld(l,mid,k<<1),bld(mid+1,r,k<<1|1);
	pushup(k);
}
void chg(int p,ll v,int l,int r,int k){
	if(!p||p>n){puts("vv");return;}
	if(l==r){t[k]=v;return;}
	int mid=l+r>>1;
	if(p<=mid)chg(p,v,l,mid,k<<1);
	else chg(p,v,mid+1,r,k<<1|1);
	pushup(k); 
}
ll ask(int L,int R,int l,int r,int k){
	if(!L||!R){puts("ww");return -1e15;}
	if(L<=l&&r<=R)return t[k];
	int mid=l+r>>1;ll ans=0;
	if(L<=mid)ans+=ask(L,R,l,mid,k<<1);
	if(R>mid)ans+=ask(L,R,mid+1,r,k<<1|1);
	return ans;
}
ll task(int x,int y){if(!x||!y)puts("[[");
	int fx=top[x],fy=top[y];ll ans=0;
	while(fx!=fy){if(!dfn[fx]||!dfn[fy])puts("Y");
		if(dep[fx]>dep[fy]){
			ans+=ask(dfn[fx],dfn[x],1,n,1);
			x=fa[fx],fx=top[x];
		}
		else {
			ans+=ask(dfn[fy],dfn[y],1,n,1);
			y=fa[fy],fy=top[y];
		}
	}
	 ans+=dfn[x]<dfn[y]?ask(dfn[x],dfn[y],1,n,1)-edg[x]:ask(dfn[y],dfn[x],1,n,1)-edg[y];
	//printf("(%d,%d,%d,%d,%d)",x,y,dfn[x],dfn[y],ask(dfn[x],dfn[y],1,n,1));
	return ans;
}
int main(){//freopen("treelink.in","r",stdin);freopen("treelink.out","w",stdout);
	cin>>n>>q;//getchar();
	for(int i=1,az=0;i<=q;i++){
		getline(cin,r);while(r.length()<3)getline(cin,r);az=0;
		a[i].o[2]=0;
		for(int j=0;j<r.length();j++){
			if(r[j]<'0'||r[j]>'9')continue;
			int x=0;
			while(j<r.length()&&r[j]>='0'&&r[j]<='9')x=(x<<1)+(x<<3)+(r[j]^48),j++;
			a[i].o[az++]=x;if(!x)puts("uu");
		}if(!a[i].o[0]||!a[i].o[1])cout<<(r.length()>0?'p':'q')<<endl;
		if(az==3)G[a[i].o[0]].push_back(a[i].o[1]),G[a[i].o[1]].push_back(a[i].o[0]);
		//for(int p=0;p<3;p++)cout<<a[i].o[p]<<' ';puts("");
	}
	for(int i=1;i<=n;i++)if(!dfn[i])rt=i,dfs(i,0),dfs2(i,0,i);
	for(int i=1;i<=n;i++)if(!dfn[i])puts("oo");
	for(int i=0;i<N;i++)edg[i]=-1e10;
	bld(1,n,1);
	for(int i=1;i<=q;i++){
		if(!a[i].o[2]){
			if(bel[a[i].o[0]]!=bel[a[i].o[1]]){puts("-1");continue;}
			if(!a[i].o[0]||!a[i].o[1])puts("]]");
			ll vv=task(a[i].o[0],a[i].o[1]);
			if(vv<0)puts("-1");else cout<<vv<<'\n';
			continue;
		}
		if(dep[a[i].o[0]]<dep[a[i].o[1]])swap(a[i].o[0],a[i].o[1]);
		chg(dfn[a[i].o[0]],a[i].o[2],1,n,1);
		edg[a[i].o[0]]=a[i].o[2];
	}
}
Csubmission
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2005;
int n,m,t,e[N][N],col[N],bk[N],f[N][N];
string s;
bool ran(int x){
	bk[col[x]]++;
	for(int i=1;i<=n;i++)
		if(i!=x&&!e[i][x]){
			if(!col[i]){
				col[i]=col[x]^1;
				if(!ran(i))return 0;
			}
			else if(col[i]==col[x])return 0;
		}
	return 1;
}
signed main(){//freopen("clique.in","r",stdin);//freopen("clique.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s;
		for(int j=1;j<=n;j++)e[i][j]=s[j-1]-'0';
	}
	for(int i=1;i<=n;i++)if(!col[i]){
		t+=2,col[i]=t;
		if(!ran(i)){puts("-1");return 0;}
	}
	memset(f,-0x3f,sizeof(f));memset(f[0],0,sizeof(f[0]));
	for(int i=2;i<=t;i+=2){
		for(int j=0;j<=n/2;j++){
			if(j>=bk[i])f[i][j]=max(f[i][j],f[i-2][j-bk[i]]+bk[i]);
			if(j>=bk[i^1])f[i][j]=max(f[i][j],f[i-2][j-bk[i^1]]+bk[i^1]);
		}
	}
	cout<<f[t][n/2]*(f[t][n/2]-1)/2+(n-f[t][n/2])*(n-f[t][n/2]-1)/2;
}
posted @ 2021-10-22 21:33  pengyule  阅读(60)  评论(0编辑  收藏  举报