BZOJ1011&luogu P3198 [HNOI2008]遥远的行星

bzoj

洛谷

这题意是不是不太清楚

真正题意:求\[f_i=\sum_{j=1}^{\lfloor i*A \rfloor} \frac{M_i*M_j}{i-j}\]

似乎只能\(O(n*\lfloor n*A \rfloor)\)

但是,注意只要结果的相对误差不超过 5% 即可

于是对于较大的\(i\)来说,\(f_i\)可以近似的看为\(M_i*\frac{\sum_{j=1}^{\lfloor i*A \rfloor} M_j}{i-\frac{\lfloor i*A \rfloor}{2}}\)

因为\(A\)是一个不超过0.35的实数,并且\(i\)较大时\(i-j\)也会比较大,所以近似一下可以接受

至于为什么,emmm你猜

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define inf 2099999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define S(a) (1<<(a-1))

using namespace std;
const int N=100+10,M=500+10;
il LL rd()
{
    re LL x=0,w=1;re char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
il void add(int x,int y)
{
  ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
}
int n,m,a[N][2],d[N],f[N][M];
int dfn[N],low[N],po[N],st[N],tt,ti;
char ista[N],cq[N];
il void tj(int x)
{
  dfn[x]=low[x]=++ti,st[++tt]=x,ista[x]=1;
  for(int i=hd[x];i;i=nt[i])
    {
      int y=to[i];
      if(!dfn[y]) tj(y),low[x]=min(low[x],low[y]);
      else if(ista[y]) low[x]=min(low[x],low[y]);
    }
  if(low[x]==dfn[x])
    {
      while(tt)
        {
          int y=st[tt--];
          ista[y]=0,po[y]=x;
          if(x==y) break;
          a[x][0]+=a[y][0],a[x][1]+=a[y][1],cq[x]=1;
        }
    }
}
il void dp(int x)
{
  //if(a[x][0]>m) return;
  f[x][a[x][0]]=a[x][1];
  for(int j=0;j<a[x][0];j++) f[x][j]=0;
  for(int i=hd[x];i;i=nt[i])
    {
      int y=to[i];
      dp(y);
      for(int k=m;k>=a[x][0];k--)
      for(int j=a[y][0];k-j>=a[x][0];j++)
        f[x][k]=max(f[x][k],f[x][k-j]+f[y][j]);
    }
}

int main()
{
  n=rd(),m=rd();
  for(int i=1;i<=n;i++) a[i][0]=rd();
  for(int i=1;i<=n;i++) a[i][1]=rd();
  for(int i=1;i<=n;i++) d[i]=rd(),add(d[i],i),po[i]=i;
  for(int i=0;i<=n;i++)
    if(!dfn[i]) tj(i);
  memset(hd,0,sizeof(hd)),tot=1;
  for(int i=1;i<=n;i++)
    if(po[i]!=po[d[i]]) add(po[d[i]],po[i]);
  for(int i=1;i<=n;i++)
    if(cq[i]&&po[i]==i) add(0,i);
  memset(f,-0x3f3f3f,sizeof(f));
  dp(0);
  int ans=0;
  for(int i=0;i<=m;i++) ans=max(ans,f[0][i]);
  printf("%d\n",ans);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/smyjr/p/9671664.html