T1:匹配


##思路:
  首先,这道题既可以用KMP,也可以用hash
  先说KMP,首先要注意的一点是:KMP的next数组求出的是boder,即既是这个串的真后缀又是真前缀,所以,对于以下类似的样例,他的输出为0,但实际是3

A:abc B:ab 增添的字符:c

  所以说,要把两个串按照A在前,B在后的顺序接起来,再跳next数组。
  再说hash,先求出两个串的hash数组,然后枚举长度匹配即可,注意ans初值一定要赋成0,对每一个匹配成功的长度取max即可。

T2:回家

思路

  这道题我在考场上想出正解了,但是Tarjan忘了怎么打了,直接WA,这题一看就是Tarjan判割点,但要注意的是,并不是所有的割点都会是答案。考虑下面的例子,节点编号为1~10;

连边有:
(1,2),(1,3),(2,4),(3,4),(4,5),(4,10);
(5,6)(10,6),(6,7),(6,8),(7,9),(8,9);

  可以发现,4,6都是割点,但答案只有4,因为6虽然是割点,但从1到10不会经过6,所以6不是必经点,由此我们发现,并不是所有割点都是必经点,要判断。
  这里有一个技巧,感谢信队提供(%%信队)的技巧。
  就是在Tarjan回溯的时候加一个判断,判断这个割点是否与n有关。详见代码。

上代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. namespace Decleration{
  4. #define ll long long
  5. #define rr register
  6. const int SIZE=2e5+5;
  7. int T,n,m;
  8. int last[SIZE];
  9. struct edge{int t,last;}a[SIZE<<2];
  10. int read(){
  11. rr int x_read=0,y_read=1;
  12. rr char c_read=getchar();
  13. while(c_read<'0'||c_read>'9'){
  14. if(c_read=='-') y_read=-1;
  15. c_read=getchar();}
  16. while(c_read<='9'&&c_read>='0'){
  17. x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
  18. c_read=getchar();}
  19. return x_read*y_read;}};
  20. using namespace Decleration;
  21. namespace Tarjan{
  22. int dfn[SIZE],low[SIZE];
  23. bool pd[SIZE],dot[SIZE];
  24. int cnt,no,root;
  25. void tarjan(int x){
  26. dfn[x]=low[x]=++cnt;
  27. int flag=0;
  28. for(int i=last[x];i!=-1;i=a[i].last){
  29. int y=a[i].t;
  30. if(!dfn[y]){
  31. tarjan(y);
  32. low[x]=min(low[x],low[y]);
  33. if(low[y]>=dfn[x]){
  34. flag++;
  35. if((x!=root||flag>1)&&pd[y]) dot[x]=1;}
  36. if(pd[y]) pd[x]=1;
  37. //假如说x的儿子与n有关,就是说他能通到n,那他就是1,因为pd[n]是一
  38. //pd[n]会把pd[y]更新为1,由此上推,所有能通到n的点的pd都会变成
  39. //1,此时如果他是割点,那他就是必经点
  40. }
  41. else low[x]=min(low[x],dfn[y]);
  42. }}
  43. };
  44. using namespace Tarjan;
  45. void Pre_Deal(){
  46. memset(last,-1,sizeof(last));
  47. memset(dfn,0,sizeof(dfn));
  48. memset(low,0,sizeof(low));
  49. memset(pd,0,sizeof(pd));
  50. memset(dot,0,sizeof(dot));
  51. cnt=no=root=0;}
  52. int main(){
  53. T=read();
  54. while(T--){
  55. n=read(),m=read();
  56. Pre_Deal();
  57. int num=0;
  58. for(rr int i=1;i<=m;i++){
  59. int u=read(),v=read();
  60. if(u==v) continue;
  61. a[++num].t=u;
  62. a[num].last=last[v];
  63. last[v]=num;
  64. a[++num].t=v;
  65. a[num].last=last[u];
  66. last[u]=num;}
  67. pd[n]=1;
  68. tarjan(1);
  69. for(rr int i=2;i<n;i++)
  70. if(dot[i]) no++;
  71. printf("%d\n",no);
  72. if(no){
  73. for(rr int i=2;i<n;i++)
  74. if(dot[i]) printf("%d ",i);}
  75. printf("\n");}
  76. }

T3:寿司

基本思路:

  首先一个贪心策略:对于每一个R我们都让他与最近的R靠近。
  考虑到这是一个环,我们将转为序列,利用类似于滚动窗口的方式,将RB串循环右移,直到恢复初始的RB串,一共循环len次。
  对于每一个右移出的结果,我们记l[i]为每一个R的左边的B的数量,r[i]为右边的,sumb为B的总数,sumr为R的总数。
  定义x[i]=l[i]-r[i],有:

ans=min(

i

=

1

s

u

m

r

\sum_{i=1}^{sumr}

∑i=1sumr​min(l[i],r[i]));

  考虑求和的优化,有:

i

=

1

s

u

m

r

\sum_{i=1}^{sumr}

∑i=1sumr​min(l[i],r[i])
=

i

=

1

s

u

m

r

\sum_{i=1}^{sumr}

∑i=1sumr​((l[i]+r[i]-|x[i]|)/2)

  显然有

l[i]+r[i]=sumb;

  记sum=

i

=

1

s

u

m

r

\sum_{i=1}^{sumr}

∑i=1sumr​x[i];

原式=(sumb*sumr-sum)>>1;

  那么就有:

ans=min((sumr*sumb-sum)>>1);

  sumb与sumr为定值但sum要实时维护,详见代码。

上代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. namespace Decleration{
  4. #define ll long long
  5. #define rr register
  6. const int SIZE=1e6+4;
  7. int T;
  8. char s[SIZE];
  9. int x[SIZE];
  10. int l[SIZE],r[SIZE];
  11. int num0,num1;
  12. inline int read(){
  13. rr int x_read=0,y_read=1;
  14. rr char c_read=getchar();
  15. while(c_read<'0'||c_read>'9'){
  16. if(c_read=='-') y_read=-1;
  17. c_read=getchar();}
  18. while(c_read<='9'&&c_read>='0'){
  19. x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
  20. c_read=getchar();}
  21. return x_read*y_read;}
  22. };
  23. using namespace Decleration;
  24. int main(){
  25. T=read();
  26. while(T--){
  27. memset(s,0,sizeof(s));
  28. memset(x,0,sizeof(x));
  29. memset(l,0,sizeof(l));
  30. memset(r,0,sizeof(r));
  31. scanf("%s",s+1);
  32. int len=strlen(s+1);
  33. int num=0;
  34. ll sumb=0,sumr=0,sum=0;
  35. num1=num0=0;
  36. //num1为x[i]中负数的个数,num0为正数
  37. priority_queue<int,vector<int>,less<int> > q;
  38. //大根堆维护x[i]中的负值
  39. for(rr int i=1;i<=len;i++)
  40. if(s[i]=='B') sumb++;
  41. else num++,l[num]=sumb,sumr++;
  42. for(rr int i=1;i<=num;i++){
  43. r[i]=sumb-l[i],x[i]=l[i]-r[i];
  44. sum+=abs(x[i]);
  45. if(x[i]>=0) num0++;//??
  46. else num1++,q.push(x[i]);}
  47. ll ans=LONG_LONG_MAX;
  48. int delta=0;
  49. //delta必须有,因为无法直接适时改变堆里的元素
  50. //是整个q集合元素里的偏移值,就是他会加上的值
  51. ans=min(ans,(sumb*sumr-sum)/2);
  52. for(rr int i=len;i>=1;i--){
  53. if(s[i]=='B'){
  54. delta+=2;
  55. sum+=(num0*2-num1*2);
  56. //每个移到序列首的B都会使所有的l[i]加1,r[i]减一,则x[i]会+2
  57. //对于负的x[i],|x[i]|-2,对于非负的x[i],|x[i]|+2;
  58. while(!q.empty()&&q.top()+delta>=0){
  59. num0++,num1--;
  60. if(q.top()+delta==1) sum+=2;
  61. //-1是特例,加2后绝对值不变,要减去
  62. q.pop();
  63. //大根堆的作用是适时将变为正值的x[i]排除
  64. }
  65. }
  66. else num0--,num1++,q.push(-sumb-delta);
  67. //delta会一直递增下去,所以-sumb要-delta
  68. ans=min(ans,(sumb*sumr-sum)/2);
  69. }
  70. printf("%lld\n",ans);
  71. }
  72. }

2021.6.11 现役

noip模拟题7的更多相关文章

  1. 【入门OJ】2003: [Noip模拟题]寻找羔羊

    这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...

  2. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

  3. 9.9 NOIP模拟题

    9.9 NOIP模拟题 T1 两个圆的面积求并 /* 计算圆的面积并 多个圆要用辛普森积分解决 这里只有两个,模拟计算就好 两圆相交时,面积并等于中间两个扇形面积减去两个三角形面积 余弦定理求角度,算 ...

  4. 8.22 NOIP 模拟题

      8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...

  5. NOIP模拟题17.9.26

    B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...

  6. noip模拟题题解集

    最近做模拟题看到一些好的题及题解. 升格思想: 核电站问题 一个核电站有N个放核物质的坑,坑排列在一条直线上.如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 任务:对于给定 ...

  7. NOIP 模拟题

    目录 T1 : grid T2 : ling T3 : threebody 数据可私信我. T1 : grid 题目:在一个\(n*n\)的方格中,你只能斜着走.为了让问题更简单,你还有一次上下左右走 ...

  8. 9.22 NOIP模拟题

    吉林省信息学奥赛 2017 冬令营                                                                                    ...

  9. 6.19 noip模拟题(题目及解析转自 hzwer 2014-3-15 NOIP模拟赛)

    Problem 1 高级打字机(type.cpp/c/pas) [题目描述] 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序 ...

  10. noip模拟题《迷》enc

    [问题背景]zhx 和他的妹子聊天.[问题描述]     考虑一种简单的加密算法.     假定所有句子都由小写英文字母构成, 对于每一个字母, 我们将它唯一地映射到另一个字母.例如考虑映射规则:a- ...

随机推荐

  1. JAVA,IDEA下的包机制

    IDEA下的包机制 在实际开发中,大型系统往往需要多人合作完成,每个程序员都要命名多个类与接口等类型,难免会定义重复的类与接口.为了避免名字冲突,java提供了包机制只要包名不同,即使类名相同,也能相 ...

  2. DC-6 靶机渗透测试

    DC-6 渗透测试 冲冲冲,好好学习 . 收获总结写在文末. 操作机:kali 172.66.66.129 靶机:DC-4 172.66.66.136 网络模式:NAT 上来一波 netdiscove ...

  3. 大厂Android岗高频面试问题:说说你对Zygote的理解!

    前言 Zygote可以说是Android开发面试很高频的一道问题,但总有小伙伴在回答这道问题总不能让面试满意, 在这你就要搞清楚面试问你对Zygote的理解时,面试官最想听到的和其实想问的应该是哪些? ...

  4. java使用Selenium操作谷歌浏览器学习笔记(一)

    下载安装 在淘宝镜像https://npm.taobao.org/mirrors/chromedriver/中下载与浏览器对应的版本 查看浏览器版本 点击查看谷歌浏览器版本 在IDEA项目中导入相关j ...

  5. JS实现自定义工具类,隔行换色、复选框全选、隔行高亮等

    很多功能都可以放在js的工具类中,在使用的时候直接调用 本次实现的功能包括: /** 0.当点击表的整行的任意位置时,第一列的复选框或者单选框均选中  1.隔行换色 2.复选框的全选效果 3.实现表格 ...

  6. windows的基本命令和环境配置

    刚开始学的时候整理的基本知识 一.windows的基础知识: 1.常用的DOS命令 盘符切换: D: 回车 进入目录: cd xxx 回退目录 返回到上一级: cd ..  返回到根目录: cd / ...

  7. VueApp 自动更新解决plus is not defined问题

    一,今天用VueApp 做自动更新调用按照网上列子直接 Plus 打包编译后出现了plus is not defined 发现需要引用document.addEventListener("p ...

  8. MaterialDesign Or ComboBox 联动查询

    <ComboBox Width="200" Height="30" x:Name="ComboxName" Text="{B ...

  9. 小知识get:利用单臂路由实现不同vlan间路由

    一.单臂路由概述 1.1.单臂路由实现不同vlan间通信 链路类型 交换机连接主机的端口为access链路 交换机连接路由器的端口为Trunk链路 子接口 路由器的物理接口可以被划分成多个逻辑接口 每 ...

  10. Elasticsearch核心技术(二):Elasticsearch入门

    本文从基本概念.基本CRUD操作.倒排索引原理.分词等部分来初识Elasticsearch. 2.1 基本概念 Elasticsearch是面向文档(Document)的,文档是所有可搜索数据的最小单 ...