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有关。详见代码。

上代码:

#include<bits/stdc++.h>
using namespace std;
namespace Decleration{
#define ll long long
#define rr register
const int SIZE=2e5+5;
int T,n,m;
int last[SIZE];
struct edge{int t,last;}a[SIZE<<2];
int read(){
rr int x_read=0,y_read=1;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9'){
if(c_read=='-') y_read=-1;
c_read=getchar();}
while(c_read<='9'&&c_read>='0'){
x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
c_read=getchar();}
return x_read*y_read;}};
using namespace Decleration;
namespace Tarjan{
int dfn[SIZE],low[SIZE];
bool pd[SIZE],dot[SIZE];
int cnt,no,root;
void tarjan(int x){
dfn[x]=low[x]=++cnt;
int flag=0;
for(int i=last[x];i!=-1;i=a[i].last){
int y=a[i].t;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
flag++;
if((x!=root||flag>1)&&pd[y]) dot[x]=1;}
if(pd[y]) pd[x]=1;
//假如说x的儿子与n有关,就是说他能通到n,那他就是1,因为pd[n]是一
//pd[n]会把pd[y]更新为1,由此上推,所有能通到n的点的pd都会变成
//1,此时如果他是割点,那他就是必经点
}
else low[x]=min(low[x],dfn[y]);
}}
};
using namespace Tarjan;
void Pre_Deal(){
memset(last,-1,sizeof(last));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(pd,0,sizeof(pd));
memset(dot,0,sizeof(dot));
cnt=no=root=0;}
int main(){
T=read();
while(T--){
n=read(),m=read();
Pre_Deal();
int num=0;
for(rr int i=1;i<=m;i++){
int u=read(),v=read();
if(u==v) continue;
a[++num].t=u;
a[num].last=last[v];
last[v]=num;
a[++num].t=v;
a[num].last=last[u];
last[u]=num;}
pd[n]=1;
tarjan(1);
for(rr int i=2;i<n;i++)
if(dot[i]) no++;
printf("%d\n",no);
if(no){
for(rr int i=2;i<n;i++)
if(dot[i]) printf("%d ",i);}
printf("\n");}
}

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要实时维护,详见代码。

上代码:

#include<bits/stdc++.h>
using namespace std;
namespace Decleration{
#define ll long long
#define rr register
const int SIZE=1e6+4;
int T;
char s[SIZE];
int x[SIZE];
int l[SIZE],r[SIZE];
int num0,num1; inline int read(){
rr int x_read=0,y_read=1;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9'){
if(c_read=='-') y_read=-1;
c_read=getchar();}
while(c_read<='9'&&c_read>='0'){
x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
c_read=getchar();}
return x_read*y_read;}
};
using namespace Decleration;
int main(){
T=read();
while(T--){
memset(s,0,sizeof(s));
memset(x,0,sizeof(x));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
scanf("%s",s+1);
int len=strlen(s+1);
int num=0;
ll sumb=0,sumr=0,sum=0;
num1=num0=0;
//num1为x[i]中负数的个数,num0为正数
priority_queue<int,vector<int>,less<int> > q;
//大根堆维护x[i]中的负值
for(rr int i=1;i<=len;i++)
if(s[i]=='B') sumb++;
else num++,l[num]=sumb,sumr++;
for(rr int i=1;i<=num;i++){
r[i]=sumb-l[i],x[i]=l[i]-r[i];
sum+=abs(x[i]);
if(x[i]>=0) num0++;//??
else num1++,q.push(x[i]);}
ll ans=LONG_LONG_MAX;
int delta=0;
//delta必须有,因为无法直接适时改变堆里的元素
//是整个q集合元素里的偏移值,就是他会加上的值
ans=min(ans,(sumb*sumr-sum)/2);
for(rr int i=len;i>=1;i--){
if(s[i]=='B'){
delta+=2;
sum+=(num0*2-num1*2);
//每个移到序列首的B都会使所有的l[i]加1,r[i]减一,则x[i]会+2
//对于负的x[i],|x[i]|-2,对于非负的x[i],|x[i]|+2;
while(!q.empty()&&q.top()+delta>=0){
num0++,num1--;
if(q.top()+delta==1) sum+=2;
//-1是特例,加2后绝对值不变,要减去
q.pop();
//大根堆的作用是适时将变为正值的x[i]排除
}
}
else num0--,num1++,q.push(-sumb-delta);
//delta会一直递增下去,所以-sumb要-delta
ans=min(ans,(sumb*sumr-sum)/2);
}
printf("%lld\n",ans);
}
}

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. .net 知新:【3】.net 5 项目结构说明和发布部署

    .net 5的项目目录结构和.net framework有些明显的变化,包括显示结构和项目文件,从这两个方面看看有哪些变化. 项目目录结构 就以上篇用的demo项目为例([.net 知新:[2] .N ...

  2. LeetCode通关:求次数有妙招,位运算三连

    分门别类刷算法,坚持,进步! 刷题路线参考: https://github.com/chefyuan/algorithm-base 大家好,我是刷题困难户老三,这一节我们来刷几道很有意思的求次数问题, ...

  3. js中判断数据类型的四种方法总结

    js中判断数据类型的四种方法 前言 在js中,我们经常需要判断数据的类型,那么哪些方法可以用来判断数据的类型呢?哪种方法判断数据类型最准确呢? 我们来一个个分析: 1.typeof typeof是一个 ...

  4. awk-05-数组

    数组 数组: 存储一系列相同类型的元素,键/值方式存储,通过下标(键)来访问值 awk 中数组称为关联数组,不仅可以使用数字作为下标,还可以使用字符串作为下标 数组元素的键和值存储在 awk 程序内部 ...

  5. MySQL-17-MHA高可用技术

    环境准备 环境准备 至少准备3台独立的虚拟机数据库实例,建议4台 这里实验只准备3台,需要配置好 基于GTID的主从复制,具体怎么配置可以参看前面的章节 db01 10.0.0.51 主库 db02 ...

  6. 012 基于FPGA的网口通信实例设计【转载】

    一.网口通信设计分类 通过上面其他章节的介绍,网口千兆通信,可以使用TCP或者UDP协议,可以外挂PHY片或者不挂PHY片,总结下来就有下面几种方式完成通信: 图8‑17基于FPGA的网口通信实例设计 ...

  7. .NET第三方补丁工具(Visual Patch)常用手册

    SetupFactory简介 这是Indigo Rose(蓝玫瑰)公司开发的一套打包-补丁解决方案的补丁工具,相比Setup Factory,他的知名度似乎不太高,网上也很少找到相关资料,但是真的很简 ...

  8. 【力扣leetcode】-787. K站中转内最便宜的航班

    题目描述: 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 p ...

  9. 题解 Game

    传送门 一有「字典序最大」什么的的就懵了--这题我颓的std 首先可以发现全局最大得分很好统计,我们令它为 \(k\) 然后我们尝试构造方案,但发现无论怎么放都可能会有后效性 发现对于一个位置,可以放 ...

  10. 从350ms到80ms,揭秘阿里工程师 iOS 短视频优化方案

    内容作为 App 产品新的促活点,受到了越来越多的重视与投入,短视频则是增加用户粘性.增加用户停留时长的一把利器.短视频的内容与体验直接关系到用户是否愿意长时停留,盒马也提出全链路内容视频化的规划,以 ...