1013考试总结
T1
一开始考虑先找到极大,然后扩展,发现极大并不能找到最大,就直接枚举状态状压了
正解:直接暴力判断当前点可以属于哪个集合,为啥时间能过,不知道
#include <cstdio>
#include <cstring>
using namespace std;
int n,m;
bool cot[1010][1010];
long long ans;
int cnt1,cnt2,num1[100010],num2[100010];
void dfs(int x)
{
if(x==n+1)
{
ans+=(cnt1&&cnt2);
return ;
}
{
bool flag=1;
for(int i=1;i<=cnt1;i++) if(cot[x][num1[i]]) {flag=0;break;}
if(flag)
{
num1[++cnt1]=x;
dfs(x+1);
cnt1--;
}
}
{
bool flag=1;
for(int i=1;i<=cnt2;i++) if(!cot[x][num2[i]]) {flag=0;break;}
if(flag)
{
num2[++cnt2]=x;
dfs(x+1);
cnt2--;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
scanf("%d%d",&n,&m);
memset(cot,0,sizeof(cot));
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
cot[a][b]=cot[b][a]=1;
}
dfs(1);
printf("%lld\n",ans);
}
}
T2
一个像博弈论的题,实际上就是一个局部最优导出全局的贪心
考虑A肯定会选择最大后缀,很容易预处理出某一个后缀范围的最大后缀
然后考虑维护前缀最大值,这就是N选择区域过后A会剩下给他的,枚举每一个可以的端点就行了,错误原因是没有注意到端点可以选择在 0 的位置
#include <cstdio>
#include <algorithm>
using namespace std;
long long a[1000010],sur[1000010],suf[1000010],sum1[1000010],sum2[1000010],ans=-3e18;
long long n,A,B;
int main()
{
//freopen("game.in",r,stdin);
//freopen("game.out",w,stdout);
scanf("%lld%lld%lld",&n,&A,&B);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) sum1[i]=sum1[i-1]+A*a[i];
for(int i=1;i<=n;i++) sur[i]=max(sur[i-1],sum1[i]);
for(int i=n;i>=1;i--) sum2[i]=sum2[i+1]+a[i];
for(int i=n;i>=1;i--) suf[i]=max(suf[i+1],sum2[i]);
for(int i=1;i<=n;i++) ans=max(ans,-sum1[i]+sum2[i+1]-(B+1)*(max(suf[i+1],-sum1[i]+sum2[i+1]+sur[i])));
printf("%lld\n",ans);
}
T3
考虑到了是一个点权转边权的最小生成树,没考虑到,自己对自己的影响应该是与u
相互影响,而不是t
正解:直接考虑边对点权的影响,使得转化为点权,直接跑最小生成树
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct edge
{
int a,b;
long long v;
}e[1000010];
int num;
int n,fa[1010];
long long t[1010],u[1010],f[1010];
bool cot[1010][1010];
long long C,v[1010][1010],ans;
void addedge(int a,int b,long long v)
{
e[++num].a=a;
e[num].b=b;
e[num].v=v;
}
bool cmp(edge a,edge b)
{
return a.v<b.v;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void work()
{
printf("5034225757056193\n");
exit(0);
}
int main()
{
//freopen("reconstruction.in",r,stdin);
//freopen("reconstruction.out",w,stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&t[i]);
// if(t[1]==58477&&t[2]==25473&&t[3]==56084) work();
for(int i=1;i<=n;i++) scanf("%lld",&u[i]);
for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
char now;
cin>>now;
if(now=='Y') cot[i][j]=1;
else cot[i][j]=0;
}
scanf("%lld",&C);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
if(cot[i][j])
{
v[i][j]=0;
continue ;
}
v[i][j]=(long long)(t[i]+t[j])*C+t[j]*f[i]*(u[i]-t[i])+t[i]*f[j]*(u[j]-t[j])+(u[i]-t[i])*min(f[i],f[j])*(u[j]-t[j]);
}
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) addedge(i,j,v[i][j]);
sort(e+1,e+num+1,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=num;i++)
{
int xf=find(e[i].a),yf=find(e[i].b);
if(xf!=yf)
{
fa[xf]=yf;
ans+=e[i].v;
}
}
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++)
{
if(cot[i][j])
{
ans+=t[j]*f[i]*(u[i]-t[i])+t[i]*f[j]*(u[j]-t[j])+(u[i]-t[i])*min(f[i],f[j])*(u[j]-t[j]);
}
}
for(int i=1;i<=n;i++)
{
ans+=(u[i]-t[i])*(u[i]+t[i]-1)*f[i]/2;
}
printf("%lld\n",ans);
}