这次的比赛是真心比较狗,我TM的写了30min的树剖ZZ地直接memset超时了

话说我既然想到差分就应该去写差分的啊!

好了不过这次Rank还挺高的,终于要打进前10了当然是假的了。

好了下面开始讲题。链接

A. 幻灯结界

一道非常基础的贪心题,我们只需要两次贪心即可解决。

首先是对于改变防御值的问题,我们可以用一个很显然并且正确的贪心:总是把机会给最小的并且这个最小值应该小于改变的值。否则就没有得到最大的利用。

然后对于下一步我们可以通过一个叫排序不等式的东西。说白了就是:大的对大的,小的对小的。这样就可以保证\(max(b_i-a_i)\)最小。

其实上面的东西只需要用正常人的思想感性理解一下即可。

然后我们就sort一下,然后扫一遍即可。

CODE

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N=200005;
  5. int a[N],b[N],n,x,y,ans;
  6. inline char tc(void)
  7. {
  8. static char fl[100000],*A=fl,*B=fl;
  9. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  10. }
  11. inline void read(int &x)
  12. {
  13. x=0; char ch=tc();
  14. while (ch<'0'||ch>'9') ch=tc();
  15. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
  16. }
  17. inline int max(int a,int b)
  18. {
  19. return a>b?a:b;
  20. }
  21. int main()
  22. {
  23. //freopen("A.in","r",stdin); freopen("A.out","w",stdout);
  24. register int i; read(n); read(x); read(y);
  25. for (i=1;i<=n;++i)
  26. read(a[i]); sort(a+1,a+n+1);
  27. for (i=1;i<=n;++i)
  28. read(b[i]); sort(b+1,b+n+1);
  29. for (i=1;i<=n&&x>0;++i)
  30. {
  31. if (a[i]>=y) break;
  32. a[i]=y; --x;
  33. }
  34. sort(a+1,a+n+1);
  35. for (i=1;i<=n;++i)
  36. ans=max(ans,b[i]-a[i]);
  37. printf("%d",ans);
  38. return 0;
  39. }

B. 时之终末

一道很不错的状压DP的题。

首先我们发现数据范围:\(a<=16\),所以果断状压。

设\(f_{i,j}\)表示前\(i\)个数中末尾\(j\)个数的情况(\(j\)不足则在前面补0),其中\(j\)是一个二进制数

其每一位分别表示对应位置上的数是否被选,例如当\(j=6\)时:

代表的状态为\(110\),即表示这个数位置\(x\)之前的\(a_{x-2}\)和\(a_{x-1}\)都被选择了(不足则补0)

所以我们就能比较轻易地写出转移方程:

  • \(f_{i,k}=max(f_{i,k},f_{i-1,j}+i>=a?s_k:0)\)(表示不选\(i\)这个位置上的数)
  • \(f_{i,k|1}=max(f_{i,k|1},f_{i-1,j}+a_i+i>=a?s_k:0)\)(表示选\(i\)这个位置上的数)

其中,\(k=j<<1\)。其实就是把之前的状态都往前1位然后把新的添加进来。

\(s_k\)表示当状态是\(k\)时,通过额外方式获得的奖励分数

那么接下来就是如何枚举这个\(s_k\)的问题了。

我们可以先分别处理出所有状态的情况,然后通过经典的枚举子集方法来解决。

我们设\(t_i\)表示一种状态为\(i\)的奖励价值,则有:

  1. for (i=0;i<=cnt;++i)
  2. for (j=i;j!=0;j=(j-1)&i)
  3. s[i]+=t[j];

以上预处理的复杂度为\(O(3^a)\)。然后我们滚存一下\(f_{i,j}\)即可

CODE

  1. #include<cstdio>
  2. #include<cstring>
  3. using namespace std;
  4. const int N=105,M=55,STATE=(1<<16)+5;
  5. int f[2][M][STATE],v[N],c[STATE],t[STATE],n,m,a,b,x,y,z,cnt,s,ans;
  6. inline char tc(void)
  7. {
  8. static char fl[100000],*A=fl,*B=fl;
  9. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  10. }
  11. inline void read(int &x)
  12. {
  13. x=0; char ch=tc(); int flag=1;
  14. while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=tc(); }
  15. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc(); x*=flag;
  16. }
  17. inline int min(int a,int b)
  18. {
  19. return a<b?a:b;
  20. }
  21. inline int max(int a,int b)
  22. {
  23. return a>b?a:b;
  24. }
  25. int main()
  26. {
  27. //freopen("B.in","r",stdin); freopen("B.out","w",stdout);
  28. register int i,j,k;
  29. read(n); read(m); read(a); read(b);
  30. for (i=1;i<=n;++i)
  31. read(v[i]);
  32. for (i=1;i<=b;++i)
  33. {
  34. read(x); read(y); s=0;
  35. for (j=1;j<=x;++j)
  36. read(z),s|=1<<(a-z);
  37. t[s]+=y;
  38. }
  39. cnt=(1<<a)-1;
  40. for (i=0;i<=cnt;++i)
  41. for (j=i;j!=0;j=(j-1)&i)
  42. c[i]+=t[j];
  43. memset(f[0],163,sizeof(f[0])); int INF=f[0][0][0]; f[0][0][0]=0;
  44. for (i=1;i<=n;++i)
  45. {
  46. int now=i&1,lst=now^1; memset(f[now],163,sizeof(f[now]));
  47. for (j=0;j<=min(i-1,m);++j)
  48. for (k=0;k<=cnt;++k)
  49. if (f[lst][j][k]!=INF)
  50. {
  51. s=(k<<1)&cnt;
  52. f[now][j][s]=max(f[now][j][s],f[lst][j][k]+(i>=a?c[s]:0));
  53. f[now][j+1][s|1]=max(f[now][j+1][s|1],f[lst][j][k]+v[i]+(i>=a?c[s|1]:0));
  54. }
  55. }
  56. for (ans=INF,i=0;i<=m;++i)
  57. for (j=0;j<=cnt;++j)
  58. ans=max(ans,f[n&1][i][j]);
  59. printf("%d",ans);
  60. return 0;
  61. }

C. 伪神

一道需要思考的题目,告诉我们有些东西是暴力树剖也剖不过去的。

首先这题目一眼就可以看出上树剖的可能性,然后我们根据题意直接主席树修改最后查询大于t的数有即可

其实这个是一个树上差分的板子题。

我们先来讲一下差分这个东西(注意这不是差分约束)。我们现在开始考虑一个问题,我们对线性上的一段区间实行全部+1的操作,然后这个数组的值的变化。

我们可以发现,操作的区间\(x,y\)之间的数它们之间的相对值是不变的

然后我们再结合前缀和的思想,令一个前缀和数组\(sum_i\)。然后我们每次操作的时候只需要把\(sum_x+1\)然后\(sum_{y+1-1}\)即可

最后我们只需要累加这个\(sum\)数组的值即可

然后对于树上的操作其实也是一样的,我们只需要在树剖过后的序列上差分即可

但是注意最后这个统计的过程是\(O(n)\)的,那么复杂度就让人受不了了。

我们再次利用差分的重要性质:操作区间内的数之间的相对着不变,我们每一次也只需要把操作过的区间单独做一下即可。中间那些没有用的直接弹掉即可。

然后就可以用一种类似于离散化并去重的方法最后sort一下累加区间即可

不过这样由于sort的复杂度只能得96pts,AC需要更高级的离线基排,这里只写了sort的96分版

具体操作还是看CODE吧

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. typedef long long LL;
  6. const int N=100005;
  7. struct edge
  8. {
  9. int to,next;
  10. }e[N<<1];
  11. int n,m,a,b,x,y,t,cnt,tot,ans,rt=1,num,sum[N],head[N],dep[N],son[N],size[N],father[N],top[N],id[N],q[N*5];
  12. inline char tc(void)
  13. {
  14. static char fl[100000],*A=fl,*B=fl;
  15. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  16. }
  17. inline void read(int &x)
  18. {
  19. x=0; char ch=tc(); int flag=1;
  20. while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=tc(); }
  21. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc(); x*=flag;
  22. }
  23. inline void write(int x)
  24. {
  25. if (x/10) write(x/10);
  26. putchar(x%10+'0');
  27. }
  28. inline void add(int x,int y)
  29. {
  30. e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
  31. }
  32. inline void swap(int &a,int &b)
  33. {
  34. int t=a; a=b; b=t;
  35. }
  36. inline void modify(int x,int y)
  37. {
  38. q[++num]=x; q[++num]=y+1; ++sum[x]; --sum[y+1];
  39. }
  40. inline void DFS1(int now,int fa,int d)
  41. {
  42. father[now]=fa; dep[now]=d; size[now]=1; int res=-1;
  43. for (register int i=head[now];i!=-1;i=e[i].next)
  44. if (e[i].to!=fa)
  45. {
  46. DFS1(e[i].to,now,d+1);
  47. size[now]+=size[e[i].to];
  48. if (size[e[i].to]>res) res=size[e[i].to],son[now]=e[i].to;
  49. }
  50. }
  51. inline void DFS2(int now,int topf)
  52. {
  53. id[now]=++tot; top[now]=topf;
  54. if (!son[now]) return;
  55. DFS2(son[now],topf);
  56. for (register int i=head[now];i!=-1;i=e[i].next)
  57. if (e[i].to!=father[now]&&e[i].to!=son[now]) DFS2(e[i].to,e[i].to);
  58. }
  59. inline void change(int x,int y)
  60. {
  61. while (top[x]!=top[y])
  62. {
  63. if (dep[top[x]]<dep[top[y]]) swap(x,y);
  64. modify(id[top[x]],id[x]); x=father[top[x]];
  65. }
  66. if (dep[x]<dep[y]) swap(x,y);
  67. modify(id[y],id[x]);
  68. }
  69. inline void updata(int x)
  70. {
  71. modify(id[x],id[x]+size[x]-1);
  72. }
  73. int main()
  74. {
  75. //freopen("C.in","r",stdin); freopen("C.out","w",stdout);
  76. register int i; read(n); read(m);
  77. memset(e,-1,sizeof(e));
  78. memset(head,-1,sizeof(head));
  79. for (i=1;i<n;++i)
  80. read(x),read(y),add(x,y),add(y,x);
  81. DFS1(rt,-1,0); DFS2(rt,rt);
  82. while (m--)
  83. {
  84. read(a); read(b); read(t);
  85. for (i=1;i<=a;++i)
  86. read(x),read(y),change(x,y);
  87. for (i=1;i<=b;++i)
  88. read(x),updata(x);
  89. q[++num]=1; q[++num]=n+1;
  90. sort(q+1,q+num+1); num=unique(q+1,q+num+1)-q-1;
  91. for (x=0,i=1;i<num;++i)
  92. x+=sum[q[i]],ans+=x>=t?q[i+1]-q[i]:0;
  93. write(ans); putchar('\n');
  94. for (i=1;i<=num;++i)
  95. sum[q[i]]=0; num=ans=0;
  96. }
  97. return 0;
  98. }

EZ 2018 06 02 NOIP2018 模拟赛(十七)的更多相关文章

  1. EZ 2018 06 10 NOIP2018 模拟赛(十八)

    好久没写blog&&比赛题解了,最近补一下 这次还是很狗的,T3想了很久最后竟然连并查集都忘写了,然后T2map莫名爆炸. Rating爆减......链接不解释 好了我们开始看题. ...

  2. EZ 2018 06 17 NOIP2018 模拟赛(十九)

    这次的题目难得的水,但是由于许多哲学的原因,第二题题意表述很迷. 然后是真的猜题意了搞了. 不过这样都可以涨Rating我也是服了. Upt:链接莫名又消失了 A. 「NOIP2017模拟赛11.03 ...

  3. EZ 2018 06 24 NOIP2018 模拟赛(二十)

    很久之前写的一套题了,由于今天的时间太多了,所以记起来就写掉算了. 这一场尽管T2写炸了,但也莫名Rank4涨了Rating.不过还是自己太菜. A. 环游世界 首先我们先排个序,想一下如果不用走回来 ...

  4. EZ 2018 03 09 NOIP2018 模拟赛(三)

    最近挺久没写比赛类的blog了 链接:http://211.140.156.254:2333/contest/59 这次的题目主要考验的是爆搜+打表的能力 其实如果你上来就把所有题目都看过一次就可以知 ...

  5. EZ 2018 05 26 NOIP2018 模拟赛(十六)

    这次难道就是传说中的标准分大赛?而且这次比赛的链接不翼而飞了 一堆人153pts然后就有Rank4?看来这个Rank4不值钱了,才涨了50+的Rating. 不过还好最后5min的时候想出了T1正解, ...

  6. EZ 2018 05 20 NOIP2018 模拟赛(十五)

    这次的比赛充满着玄学的气息,玄学链接 首先讲一下为什么没有第十四场 其实今天早上9点时看到题目就叫了:原题! 没错,整套试卷都做过,我还写了题解 然后老叶就说换一套,但如果仅仅是这样就没什么 但等13 ...

  7. EZ 2018 05 13 NOIP2018 模拟赛(十三)

    这次的比赛真心水,考时估分240,然后各种悠闲乱逛 然后测完T1数组开小了炸成40,T2,T3都没开long long,T2炸成20,T3爆0 掉回1600+的深渊,但是还有CJJ dalao比我更惨 ...

  8. EZ 2018 05 04 NOIP2018 模拟赛(十二)

    这次的试卷应该是激励我们一下的,链接 然后大家的分数就都很高,然后我就210被一群秒A T2的240大佬爆踩 掉了5rating但Rank竟然发杀了 X_o_r dalao && YZ ...

  9. EZ 2018 05 01 NOIP2018 模拟赛(十一)

    莫名其妙暴涨Rating 其实题目都挺好挺简单的,但是越简单就越容易ZZ 不理解问什么第一题这么多人找环 不过T2是真心细节题,T3太难了 题目戳这里 T1 仔细分析题意发现那个交换规则就是废话,如果 ...

随机推荐

  1. 网络基础 cookie详解

    cookie详解 by:授客 QQ:1033553122 cookie干嘛用的? 参见文章http 会话(session)详解: 网络基础 http 会话(session)详解   cookie分类 ...

  2. Rxjava学习(二操作符)

    操作符是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件 1.filter filter()操作符是可 ...

  3. 洗礼灵魂,修炼python(30)--装饰器(2)—>装饰器总结+进阶使用

    在上一篇博文的经典案例中,我想你应该对装饰器有很好的了解了,不过光有那些还不够真的,还需要总结和进阶一下,所以本篇博文解析装饰器进阶. 装饰器 1.什么是装饰器? 个人理解:装饰器又叫语法糖,指的是对 ...

  4. 【公众号系列】在SAP里查看条件记录的方法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[公众号系列]在SAP里查看条件记录的方法   ...

  5. jQuery 实现图片动画代码

    向下移动动画 $(".image").click(function(){ $(this).animate({height:'0px'}) }); <!doctype html ...

  6. java -jar 命令

    java -jar spring.jar 这个命令当你 controller c 之后,程序就自动结束了 java jar spring.jar & &是指在后台运行,但当用户推出(挂 ...

  7. java基础-温故而知新(02)

    基本数据的自动拆装箱及享元设计模式 1.1 自动装箱        -128~127 之间的整数,装在一个内存区域.         超过这个范围的整数,装在不同的内存区域. 1.2 自动拆箱     ...

  8. 控件布局_TableLayout

    <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=" ...

  9. 记录清除wnTKYg挖矿工木马(守护进程ddg.xxxx)的过程

    起因,阿里云多次提醒我的一台服务器有恶意发包行为,且给出了一些解决办法.之前也没太在意,就按照解决办法处理了一下.然后过一段时间,还是提示有此行为. 猜肯定是中了木马了,开始以为是被肉鸡了拿来做DDo ...

  10. 1346:【例4-7】亲戚(relation)

    并查集的模板题: #include<iostream> #include<cstdio> using namespace std; ; int fa[maxn]; int fi ...