[关闭]
@dxbdly 2020-12-20T07:02:36.000000Z 字数 3541 阅读 200

G2020寒假训练赛2

信息学——模拟赛


T1. TIME IS MOONEY

考虑

设:表示第天到达城市的最大收益

则容易得出:

由于的前继,所以考虑建反向边。

答案为:

那么最后只需确定的范围即可。

取最小值,点权均为最大值

则此时取最大值

所以可得

  1. //The code is from dxbdly
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x=0;
  7. char c=getchar();
  8. bool f=0;
  9. while (!isdigit(c))
  10. f=f|(c=='-'),c=getchar();
  11. while (isdigit(c))
  12. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  13. return f?-x:x;
  14. }
  15. int n,m,c;
  16. int w[1005];
  17. struct node{
  18. int v,nex;
  19. }edge[4005];
  20. int head[1005],len,f[1005][1005],ans;
  21. inline void make_map(int u,int v)
  22. {
  23. len++;
  24. edge[len].nex=head[u];
  25. edge[len].v=v;
  26. head[u]=len;
  27. }
  28. int main(){
  29. n=read(),m=read(),c=read();
  30. for (register int i=1;i<=n;++i)
  31. w[i]=read();
  32. for (register int i=1;i<=m;++i)
  33. {
  34. int u=read(),v=read();
  35. make_map(v,u);
  36. }
  37. memset(f,-0x7f,sizeof(f));
  38. f[0][1]=0;
  39. for (register int i=1;i<=1000;++i)
  40. {
  41. for (register int x=1;x<=n;++x)
  42. for (register int j=head[x];j;j=edge[j].nex)
  43. {
  44. int y=edge[j].v;
  45. if (f[i-1][y]>=0)
  46. f[i][x]=max(f[i][x],f[i-1][y]+w[x]);
  47. }
  48. ans=max(ans,f[i][1]-c*i*i);
  49. }
  50. printf("%d",ans);
  51. return 0;
  52. }

T2. FARMER JOHN SOLVES 3SUM

因为只有,而询问很大有

可以考虑离线算法。

表示的范围内,有多少个使得

我们枚举,

由于之间只多了一个数。

所以考虑对于每个开个桶,每次将当前的丢到桶里去。

那么我们就可以用的时间预处出所有

我们对做二维前缀和,记作

那么询问相当于就是要求以为左下角,以为右上角的矩阵和。

那么直接容斥一下就好了。

还有一个地方需要注意,由于可能有负数,所有需要先加一个,才能开桶,处理一下就好。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. inline int read()
  4. {
  5. int x=0;
  6. char c=getchar();
  7. bool f=0;
  8. while (!isdigit(c))
  9. f=f|(c=='-'),c=getchar();
  10. while (isdigit(c))
  11. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  12. return f?-x:x;
  13. }
  14. const int INF=1e6;
  15. int n,q;
  16. int a[5005],cnt[2000005];
  17. long long f[5005][5005];
  18. int main(){
  19. n=read(),q=read();
  20. for (register int i=1;i<=n;++i)
  21. a[i]=read(),a[i]+=INF;
  22. for (register int i=1;i<=n;++i)
  23. {
  24. for (register int j=i+1;j<=n;++j)
  25. {
  26. if (j>i+1&&a[i]+a[j]<=3*INF&&a[i]+a[j]>=INF)
  27. f[i][j]=cnt[3*INF-a[i]-a[j]];
  28. cnt[a[j]]++;
  29. }
  30. for (register int j=i+1;j<=n;++j)
  31. cnt[a[j]]--;
  32. }
  33. for (register int i=1;i<=n;++i)
  34. for (register int j=1;j<=n;++j)
  35. f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
  36. while (q--)
  37. {
  38. int l=read(),r=read();
  39. printf("%lld\n",f[r][r]-f[l-1][r]-f[r][l-1]+f[l-1][l-1]);
  40. }
  41. return 0;
  42. }

T3. SPRINGBOARDS

考虑

为了方便,我们先加上两个跳板。

个跳板

个跳板

设:为走到第个跳板,所花费的最小代价。

则:

这样的话时间复杂度是的。

考虑拿树状数组维护

则时间复杂度降到,可过。

注意数据较大,需要对进行离散化。

  1. //The code is from dxbdly
  2. #include<bits/stdc++.h>
  3. #define INF INT_MAX
  4. using namespace std;
  5. inline int read()
  6. {
  7. int x=0;
  8. char c=getchar();
  9. bool f=0;
  10. while (!isdigit(c))
  11. f=f|(c=='-'),c=getchar();
  12. while (isdigit(c))
  13. x=(x<<3)+(x<<1)+(c^48),c=getchar();
  14. return f?-x:x;
  15. }
  16. int n,m;
  17. struct node{
  18. int x,y,b,id;
  19. }a[200005];
  20. int ls[200005],tot,len,c[200005],f[200005];
  21. inline bool operator <(node x,node y)
  22. {
  23. return x.x!=y.x?x.x<y.x:x.y<y.y;
  24. }
  25. inline int lowbit(int x)
  26. {
  27. return x & (-x);
  28. }
  29. inline void update(int x,int num)
  30. {
  31. while (x<=tot)
  32. c[x]=min(c[x],num),x+=lowbit(x);
  33. }
  34. inline int query(int x)
  35. {
  36. int minn=INF;
  37. while (x)
  38. minn=min(minn,c[x]),x-=lowbit(x);
  39. return minn;
  40. }
  41. int main(){
  42. n=read(),m=read();
  43. ls[++tot]=0,ls[++tot]=n,a[++len]=(node){0,0,0,0},a[++len]=(node){n,n,1,m+1};
  44. for (register int i=1;i<=m;++i)
  45. {
  46. int x1=read(),y1=read(),x2=read(),y2=read();
  47. ls[++tot]=y1,ls[++tot]=y2;
  48. a[++len]=(node){x1,y1,1,i},a[++len]=(node){x2,y2,0,i};
  49. }
  50. sort(ls+1,ls+tot+1);
  51. int cnt=unique(ls+1,ls+tot+1)-ls-1;
  52. for (register int i=1;i<=len;++i)
  53. a[i].y=lower_bound(ls+1,ls+cnt+1,a[i].y)-ls;
  54. sort(a+1,a+len+1);
  55. for (register int i=1;i<=tot;++i)
  56. c[i]=INF;
  57. for (register int i=1;i<=len;++i)
  58. {
  59. if (a[i].b)
  60. f[a[i].id]=query(a[i].y)+a[i].x+ls[a[i].y];
  61. else
  62. update(a[i].y,f[a[i].id]-a[i].x-ls[a[i].y]);
  63. }
  64. printf("%d",f[m+1]);
  65. return 0;
  66. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注