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