noip模拟7[匹配·回家·寿司]
这次考试状态好像还是没有回来,只拿了55pts,还全是第一题的功劳,就是一个小KMP,然后还让我给打错了
就很难受,while打成了if,然后wa掉45分考完立马拿回来了,悔死了,害
第二题爆零了,为什么??问就是板子没背过,tarjan的割点,还有缩点(其实用不到,但是我也不会QWQ)
第三题也爆零了,为什么??问就是我是大傻瓜,看到题u就想睡觉,困的眼都睁不开
俺也不知道为啥,这睡得越多越困,为啥啊,不知道
这次考试其实给了我很大的信心,让我不要见到题就跑,毕竟还是有简单题的哈哈哈
下次会考的更好
这就是一个小KMP,hash也行,好像比我KMP还快,真不知道为啥
害,就直接KMP就完事了,好像我还打假了,别人都比我快
人家都是直接ab串去匹配,我是aa自己匹配,然后哦拿着b在上面跑
代码

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define re register int
4 const int N=1000005;
5 int T,la,lb;
6 char a[N],b[N],p[5];
7 int fail[N];
8 signed main(){
9 scanf("%d",&T);
10 while(T--){
11 memset(fail,0,sizeof(fail));
12 scanf("%d%d",&la,&lb);
13 scanf("%s",a+1);
14 //for(re i=1;i<=la;i++)cout<<a[i]<<" ";
15 for(re i=1;i<=lb;i++)b[i]=a[i];
16 scanf("%s",p);
17 b[++lb]=p[0];
18 int j=0;
19 for(re i=2;i<=la;i++){
20 //cout<<j<<" ";
21 if(a[j+1]!=a[i]&&j>0)j=fail[j];
22 //cout<<j<<" ";
23 if(a[j+1]==a[i])j++;
24 //cout<<j<<endl;
25 fail[i]=j;
26 }
27 j=0;int ans=0;
28 for(re i=0;i<=lb;i++){
29 while(b[i+1]!=a[j+1]&&j>0)j=fail[j];
30 if(b[i+1]==a[j+1]&&j<la)j++;
31 if(i+1==lb)ans=max(ans,j);
32 //cout<<j<<" "<<a[j]<<endl;
33 }
34 printf("%d\n",ans);
35 }
36 }
T1
要不是我考场上把板子给忘了,至于拿零分???????
这一看就能看出来是tarjan的割点的板子吧,可惜我忘了
然后 注意我们直接判断出来的割点并不是最终的必须经过的点
所以我们在判断割点的时候,加上一个判断,判断一下这个点能不能把n给割掉
就是定义一个pd数组
然后pd[n]=1;根据深搜的顺序向上转移
就行了,代码

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define re register int
4 const int N=400005;
5 int T,n,m;
6 int to[N*2],nxt[N*2],head[N],rp;
7 int dfn[N],low[N],cnt,cut[N];
8 bool pd[N];
9 int ans;
10 void add_edg(int x,int y){
11 to[++rp]=y;
12 nxt[rp]=head[x];
13 head[x]=rp;
14 }
15 void dfs(int x){
16 dfn[x]=low[x]=++cnt;
17 for(re i=head[x];i;i=nxt[i]){
18 int y=to[i];
19 if(!dfn[y]){
20 dfs(y);
21 low[x]=min(low[x],low[y]);
22 if(low[y]>=dfn[x])
23 if(x!=1&&pd[y])
24 cut[x]=1,ans++;
25 if(pd[y])pd[x]=1;
26 }
27 else low[x]=min(low[x],dfn[y]);
28 }
29 }
30 signed main(){
31 scanf("%d",&T);
32 while(T--){
33 rp=0;
34 //memset(low,0,sizeof(low));
35 cnt=0;
36 scanf("%d%d",&n,&m);
37 for(re i=1;i<=n;i++){
38 cut[i]=0;pd[i]=0;
39 dfn[i]=0;head[i]=0;
40 }
41 for(re i=1;i<=m;i++){
42 int x,y;
43 scanf("%d%d",&x,&y);
44 add_edg(x,y);
45 add_edg(y,x);
46 }
47 pd[n]=1;
48 ans=0;
49 dfs(1);
50 printf("%d\n",ans);
51 for(re i=2;i<n;i++)
52 if(cut[i])printf("%d ",i);
53 printf("\n");
54 }
55 }
T2
不说这个题是毒瘤题吧,反正就挺迷的,因为,要你统计最小步数,然后我第一时间就想到了区间dp
然后想到了石子合并,然后思路就断了,然后我就想睡觉,然后就完蛋了
首先我们看到这个题,我们很容易看出来,我们要找到一个断点,分割点是把这个环分割成一个链
就是把环状的问题转换成链状的问题
然后我们就可以枚举这个断点了,肯定每一种情况的移动都不会经过断点(显然的)
我们设只动R,因为在R动的同时,交换,B也会跟着一起动
我们还可以找到一个分界点,就是这个分界点两侧的R都不会向相反的方向移动
就是左边的去左边,右边的去右边
还可以看出来,每一个R 移动的步数就是min(l[i],r[i]);(l[i]为R左侧B的数量,r[i]为R右侧B的数量)
这样我们就成功的搞出了O(n2)的算法:直接枚举断点,然后O(n)计算每个R的min(l[i],r[i]),然后求和即可,最后再取个最小值,40pts
然后我就去搞了个优化,优化完还是40就很无奈,然后去找正解了(我用的O(nlogn)的,还有O(n)的,不过那个人的常数有亿点点大,比我慢了3000ms)
现在考虑原来的式子:(设tot0表示R的个数,tot1表示B的个数,l[i]+r[i]=tot1)
$ ans=\min\sum\limits_{i}^{tot_0}\min(l[i],r[i]) $
$ ans=\min\sum\limits_{i}^{tot_0}\frac{l[i]+r[i]-\left | l[i]-r[i] \right | }{2} $
$ ans=\min\sum\limits_{i}^{tot_0}\frac{tot_1-\left | l[i]-r[i] \right | }{2} $
$ ans=sam+\max\sum\limits_{i}^{tot_0}\frac{\left | l[i]-r[i] \right | }{2} $(sam为tot1*tot0/2)
这时候,sam变成了定植,我们只需要去求后面的式子的最大值就行了
我们还要考虑由上一次向这一次转移,我们可以枚举这长度为n的区间的起点,直接在这个序列上枚举就可以了
从1~n,我们依次把第一个字符放到整个串的末尾,这样就模拟了,枚举每一个断点的过程
设x[i]=l[i]-r[i];
然后分类讨论,如果放的是R ,那么这个R的x[i]就变成tot1
如果是B,那么每一个下x[i]都减去2
但是这里有一个非常恶心的地方,我们都知道正数减2,绝对值减小
负数减2,绝对值增加
但是如果是1的话,我们就要进行特判,不能操作,因为绝对值没变
所以我们将所有的x[i]加入到一个小根堆里,这样每次在堆首取得最小的正数,然后进行转移
你是不是在想,怎么对0进行操作,0我们把它放到负数中,因为它减2之后绝对值会增加
而且,关于如何对队列里的数进行操作,因为我们每一次转移都要对所有的x[i]-2,但是为了保证复杂度,我们有只能枚举堆头的几个值
所以我们用到一个变量seg,记录我们转移了几个B,这样我们每次将堆头与2*seg去比较,来判断是否弹出
然后记得转移R的时候,向队尾加入的是tot1+2*seg
然后这个题就愉快的解出来了,对于上面的解释可能有些模糊,所以可以先试着将队列全部弹出,-2后在push进去,然后再考虑我这个算法
代码

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define int long long
4 #define re register int
5 const int N=1000005;
6 int T,n;
7 char a[N];
8 int tot[2];//0 R 1 B
9 int l[N],r[N];
10 priority_queue<int,vector<int>,greater<int> > q;
11 signed main(){
12 scanf("%lld",&T);
13 while(T--){
14 while(!q.empty())q.pop();
15 memset(tot,0,sizeof(tot));
16 memset(l,0,sizeof(l));
17 int sum=0,maxn=0,zh=0,fu=0;
18 scanf("%s",a+1);
19 n=strlen(a+1);
20 for(re i=1;i<=n;i++){
21 l[i]=l[i-1];
22 if(a[i]=='R')tot[0]++;
23 else tot[1]++,l[i]++;
24 }
25 for(re i=1;i<=n;i++){
26 if(a[i]=='R'){
27 r[i]=tot[1]-l[i];
28 sum+=abs(l[i]-r[i]);
29 if(l[i]-r[i]>0)q.push(l[i]-r[i]),zh++;
30 else fu++;
31 }
32 }
33 int seg=0;
34 maxn=max(maxn,sum);
35 for(re i=1;i<n;i++){
36 if(a[i]=='B'){
37 seg++;
38 sum+=2*fu;
39 while(!q.empty()){
40 if(q.top()-seg*2>0)break;
41 else if(q.top()-seg*2==0){
42 sum-=2;zh--;fu++;
43 q.pop();
44 }
45 else{
46 zh--;fu++;
47 q.pop();
48 }
49 }
50 sum-=2*zh;
51 maxn=max(maxn,sum);
52 }
53 else{
54 zh++;fu--;
55 q.push(tot[1]+2*seg);
56 }
57 //cout<<i<<endl;
58 }
59 printf("%lld\n",(tot[1]*tot[0]-maxn)/2);
60 }
61 }
T3

noip模拟7[匹配·回家·寿司]的更多相关文章
- noip 模拟赛 匹配 //贪婪策略
匹配(match.pas/match.c/match.cpp) [题目描述] 到了新的学期,Mcx痛苦的发现通用技术课居然是有实验课的,这样的话他就不得不放弃写作业的想法而去做一件类似于搭积木的事情. ...
- NOIP模拟测试8「寿司」
考试时打的类似$n^2$暴力,然后炸了只有10分 后来验证我的算法伪了. 题解 显然你有一种解法,假设你要在一个B点断开将R分别移向最左 最右,这样只用分别计算B点右面蓝色数量左面蓝色数量就得到了一个 ...
- NOIP模拟赛-2018.11.6
NOIP模拟赛 今天想着反正高一高二都要考试,那么干脆跟着高二考吧,因为高二的比赛更有技术含量(我自己带的键盘放在这里). 今天考了一套英文题?发现阅读理解还是有一些困难的. T1:有$n$个点,$m ...
- NOIP模拟赛-2018.11.5
NOIP模拟赛 好像最近每天都会有模拟赛了.今天从高二逃考试跑到高一机房,然而高一也要考试,这回好像没有拒绝的理由了. 今天的模拟赛好像很有技术含量的感觉. T1:xgy断句. 好诡异的题目,首先给出 ...
- 20190908 NOIP 模拟40
考试过程: 刚看完题,发现T1是个类lis 问题,但要求$O(nlogn)$,应该是个数据结构优化dp,T2应该是个数据结构,T3是个字符串?没有匹配,不会是后缀数组吧,这是NOIP模拟啊,可能是个d ...
- noip模拟44[我想我以后会碰见计数题就溜走的]
noip模拟44 solutions 这一场抱零的也忒多了,我也只有45pts 据说好像是把几套题里面最难的收拾出来让我们考得 好惨烈啊,这次的考试我只有第一题骗了40pts,其他都抱零了 T1 Em ...
- noip模拟45[真是啥也不会]
noip模拟45 solutions 真是一个题都不会了,然而考完试之后我在10min之内切掉了最后一个题 话说这是为什么呢, 因为最后一个是回滚莫队的大板子,然而我忘记了,不不不,是没有记起来过 T ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
随机推荐
- Django(21)migrate报错的解决方案
前言 在讲解如何解决migrate报错原因前,我们先要了解migrate做了什么事情,migrate:将新生成的迁移脚本.映射到数据库中.创建新的表或者修改表的结构. 问题1:migrate怎么判断哪 ...
- .NET程序崩溃了怎么抓 Dump ? 我总结了三种方案
一:背景 1. 讲故事 最近几天接到了几个crash的求助,可能这几个朋友没玩过怎么去生成dump,只能手把手教,感觉也不是一个办法,所以有必要总结一下,后续再有朋友咨询的话,我就可以把这篇文章丢过去 ...
- APP专项测试实战1
首先,如果测试需要用到的话,还是建议一下大家去看下Android-studio的官方文档.文档地址:Documentation | Android 开发者 | Android Develope ...
- Envoy:TLS双向认证
环境准备 主机 角色 数量 front-envoy front envoy 1 service envoy 作为内部后端的envoy 2 end 后端应用程序 2 访问 / front-envoy = ...
- [bug] Unrecognized token 'code': was expecting (JSON String, Number, Array, Object,'true', 'false' or 'null')
JSON格式有误,需用JSON.stringify()函数转换一下 参考 https://www.cnblogs.com/sunyanblog/p/13788740.html https://www. ...
- 【CentOS_7】一行shell实现自动清理过期日志
昨日web测试环境登录白屏,慌忙登上机器查看,半天没找到问题. 不知哪根筋不对,df -h 一看 , /dev/sda1 已经100%. 立马 du -sh *,发现log日志有点大. 手工清理后,业 ...
- gpgj-19.高级课总结
19.高级课总结 1.高级课最终站 如何对公司估值 找到公司未来的真实盈利*回本年限=估值 如何计算公司未来的盈利 ROIC 资本回报率 零售公司 每平米净现金流 经营面积 高速公路 每 ...
- linux中级之防火墙的数据传输过程
网络数据传输过程 netfilter在数据包必须经过且可以读取规则的位置,共设有5个控制关卡.这5个关卡处的检查规则分别放在5个规则链中(有的叫钩子函数(hook functions).也就是说5条链 ...
- CAP 与数据一致性
分布式系统的假设是,工作在网络环境下的系统拥有多个节点,而这些节点本身会由于各种原因而变得不稳定.这其中就有一个非常重要的概念--CAP原理.这个原理指导着大多数分布式系统的设计过程,CAP原理大致是 ...
- JavaEE 三层架构模式
什么是架构模式 要理解三层架构模式,我们得先搞清楚什么是架构模式.(这里说的架构模式是针对后端开发) 所谓架构就是系统最高级别的设计,一个系统特别复杂时才需要架构设计,如果只是开发一个很小程序,就谈不 ...