Loading

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);
}
posted @ 2020-10-13 17:50  zzqDeco  阅读(77)  评论(0编辑  收藏  举报