【解题报告】SRM-08
A
Description
给一个 01 串设为其 S,询问是否存在只出现两次的 01 串 T。
这里的出现定义为存在一串下标 ,满足
且
。
Input
一行,一个 01 串
Output
一行,字母 Y 表示存在,N 表示不存在
HINT
1.设串 S 的长度为 n,。
2.设串 S 的长度为 n,。
3.设串 S 的长度为 n,。
4.数据为随机生成。
对于第一部分,随意骗一骗分?
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char s[],num0,num1;
int main()
{
scanf("%s",s);
int len=strlen(s);
for(int i=;i<len;i++)
if(s[i]=='')num0++;
else num1++;
if((num0%&&num1%)||num0==||num1==)printf("N");
else printf("Y");
return ;
}
对于第二部分,暴力dfs。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=<<;
int n,a[],calc[][N];
char s[];
bool f;
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void dfs(int x,int sum,int num,int k)
{
sum=sum*+a[x];
if(a[x]||k)k=;
else num++;
calc[num][sum]++;
for(int i=x+;i<=n;i++)dfs(i,sum,num,k);
}
int main()
{
scanf("%s",s);
n=strlen(s);
for(int i=;i<n;i++)a[i+]=s[i]-'';
for(int i=;i<=n;i++)dfs(i,,,);
int summ=<<n;
for(int i=;i<=n;i++)
for(int j=;j<summ;j++)
if(calc[i][j]==){f=true;break;}
if(f)printf("Y");
else printf("N");
return ;
}
对于第三部分,注意特判0和1的个数恰好为2的情况。
对于其他情况,若存在形如abcd(a!=b,b==c,c!=d)(即0110或1001)类型的子串,则输出Y:此时T为 b前面的所有数字+b(也是c)+后面的所有数字。若不存在,则输出N:对于相邻相同数字长度超过2的子串,在T中必定是全部出现,否则会出现3种及3种以上情况,不满足T的要求;对于相邻数字互不相同的子串,不管怎么选只有一种或多种情况,不满足出现次数恰好为2,此时对于这部分子串倾向于全选(保持出现次数小于2)。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,zero;
char s[];
bool f;
int main()
{
scanf("%s",s+);
n=strlen(s+);
for(int i=;i<=n;i++)
if(s[i]=='')zero++;
if(zero==||n-zero==)f=true;
for(int i=;i<n-;i++)
if(s[i]!=s[i+]&&s[i+]==s[i+]&&s[i+]!=s[i+])f=true;
if(f)printf("Y");
else printf("N");
return ;
}
B
Description
给长度为 n 的数列 A 和长度为 m 的数列 B,问有多少长度为 m 的数列 C 满足
且
Input
第一行俩整数 n 和 m
第二行 n 个整数 ,表示数列 A
第三行 m 个整数 ,表示数列 B
Output
一个整数,表示满足条件的数列 C 的个数模 后的值。
HINT
1.
2.
3.
对于第一部分,比赛时暴力dfs。(不要问我为什么不写dp
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,ans,a[],b[];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void dfs(int x,int deep)
{
if(m-deep>n-x)return;
if(deep==m){ans++;return;}
for(int i=x+;i<=n;i++)
if(a[i]-a[x]+b[deep]>=)dfs(i,deep+);
}
int main()
{
n=read();m=read();
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=m;i++)b[i]=read();
if(m==){printf("%d",n);return ;}
for(int i=;i<m;i++)b[i]=b[i+]-b[i];
for(int i=;i<=n;i++)dfs(i,);
printf("%d",ans);
return ;
}
对于第二、三部分,dp+树状数组。
为了方便操作,先进行离散化。num数组是一个队列,存的是原数列离散化后的编号所对应的原值(下标为1~cnt);id[i]代表原数列中下标为i的数字离散化后的编号。
每次都枚举b[i]并重新计算g数组(g[j]代表满足num[k]+b[i-1]<=num[j]+b[i]中k的最大值)。
然后就是愉快的单点修改区间查询了√
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=;
const int mod=1e9+;
int n,m,cnt,ans;
int b[N],id[N],num[N],t[N],f[N],g[N];
struct node{int w,pos;}a[N];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
bool cmp(node a,node b){return a.w<b.w;}
int lowbit(int x){return x&-x;}
void insert(int x,int v)
{
while(x<=n)
{
t[x]=(t[x]+v)%mod;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=;
while(x)
{
ans=(ans+t[x])%mod;
x-=lowbit(x);
}
return ans;
}
int main()
{
n=read();m=read();
for(int i=;i<=n;i++)
a[i].w=read(),a[i].pos=i,f[i]=;
sort(a+,a+n+,cmp);
for(int i=;i<=n;i++)
if(a[i].w==a[i-].w)id[a[i].pos]=cnt;
else id[a[i].pos]=++cnt,num[cnt]=a[i].w;
for(int i=;i<=m;i++)b[i]=read();
for(int i=;i<=m;i++)
{
for(int j=;j<=cnt;j++)
{
int u=g[j-];
while(u<cnt&&num[u+]+b[i-]<=num[j]+b[i])u++;
g[j]=u;
}
memset(t,,sizeof(t));
insert(id[i-],f[i-]);
for(int j=i;j<=n;j++)
{
int sum=f[j];
f[j]=query(g[id[j]]);
insert(id[j],sum);
}
}
for(int i=m;i<=n;i++)ans=(ans+f[i])%mod;
printf("%d",ans);
return ;
}
C
Description
给一个图,n 个点 m 条双向边,每条边有其长度。n 个点中有 k 个是特殊点,问任意两个特殊点的最短路是多少。
Input
第一行三个整数 n m k
第二行 k 个整数 ,为各个特殊点
接下来 m 行,每行三个整数 x y d,表示 x 到 y 有一条长度为 d 的边
Output
一个整数
HINT
1.
2.
3.
4.图为联通图
对于第一部分,Floyd水过。(注意重边和自环!)
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,k,x,y,d,t,ans=inf;
int dis[][];
bool f[];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int main()
{
n=read();m=read();k=read();
for(int i=;i<=k;i++)
{
t=read();
f[t]=true;
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(i!=j)dis[i][j]=inf;
for(int i=;i<=m;i++)
{
x=read();y=read();d=read();
dis[x][y]=dis[y][x]=min(dis[x][y],d);
if(f[x]&&f[y]&&x!=y)ans=min(ans,dis[x][y]);
}
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j] )
{
dis[i][j]=dis[i][k]+dis[k][j];
if(f[i]&&f[j])ans=min(ans,dis[i][j]);
}
printf("%d",ans);
return ;
}
对于第二部分,跑k次SPFA。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=;
const int inf=0x3f3f3f3f;
int n,m,k,x,y,t,cnt,ans=inf;
int first[N],a[N],dis[N],q[N];
bool f[N],in[N];
struct edge{int next,to,w;}e[N*];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void ins(int x,int y,int w){cnt++;e[cnt].to=y;e[cnt].w=w;e[cnt].next=first[x];first[x]=cnt;}
void spfa(int S)
{
memset(in,,sizeof(in));
memset(dis,0x3f,sizeof(dis));
int head=,tail=;
q[]=S;in[S]=true;dis[S]=;
while(head!=tail)
{
int u=q[head++];in[u]=false;
if(head>)head=;
for(int i=first[u];i;i=e[i].next)
{
int v=e[i].to;
if(dis[u]+e[i].w<dis[v])
{
dis[v]=dis[u]+e[i].w;
if(f[v])ans=min(ans,dis[v]);
if(!in[v]){q[tail++]=v;in[v]=true;if(tail>)tail=;}
}
}
}
}
int main()
{
n=read();m=read();k=read();
for(int i=;i<=k;i++)a[i]=read(),f[a[i]]=true;
for(int i=;i<=m;i++)
{
x=read();y=read();t=read();
ins(x,y,t);ins(y,x,t);
}
for(int i=;i<=k;i++)spfa(a[i]);
printf("%d",ans);
return ;
}
对于第三部分,对于每个点,维护以下信息:离它最近的特殊点及路程,离它次近的特殊点及路程(且需保证两个特殊点不同)。最后再枚举点,用最短路+次短路来更新答案。(看到好多大佬都是枚举边……瑟瑟发抖。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=;
const int inf=0x3f3f3f3f;
int n,m,k,cnt,x,y,w,ans=inf;
int a[],first[N],fir[N],sec[N],firn[N],secn[N];
struct edge{int to,next,w;}e[N*];
struct node
{
int d,id;
bool operator <(const node& x)const{return x.d<d;}
};
priority_queue<node>q;
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(x=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void ins(int x,int y,int w)
{
cnt++;e[cnt].to=y;e[cnt].w=w;
e[cnt].next=first[x];first[x]=cnt;
}
void dijkstra()
{
memset(fir,0x3f,sizeof(fir));
memset(sec,0x3f,sizeof(sec));
for(int i=;i<=k;i++)
{
fir[a[i]]=;firn[a[i]]=a[i];
q.push((node){,a[i]});
}
while(!q.empty())
{
node x=q.top();q.pop();
if(x.d>fir[x.id])continue;
int now=x.id;
for(int i=first[now];i;i=e[i].next)
{
int to=e[i].to;
if(firn[now]==firn[to])
{
if(fir[now]+e[i].w<fir[to])
fir[to]=fir[now]+e[i].w,q.push((node){fir[to],to});
}
else if(fir[now]+e[i].w<fir[to])
{
sec[to]=fir[to];secn[to]=firn[to];
fir[to]=fir[now]+e[i].w;firn[to]=firn[now];
q.push((node){fir[to],to});
// printf("[fir]%d %d %d [n] %d %d\n",now,to,fir[to],firn[now],firn[to]);
}
else if(fir[now]+e[i].w<sec[to])
{
sec[to]=fir[now]+e[i].w;
secn[to]=firn[now];
// printf("[sec]%d %d %d [n] %d %d\n",now,to,sec[to],secn[now],secn[to]);
}
}
}
}
int main()
{
n=read();m=read();k=read();
for(int i=;i<=k;i++)a[i]=read();
for(int i=;i<=m;i++)
{
x=read();y=read();w=read();
ins(x,y,w);ins(y,x,w);
}
dijkstra();
for(int i=;i<=n;i++)ans=min(ans,fir[i]+sec[i]);
printf("%d",ans);
return ;
}
【解题报告】SRM-08的更多相关文章
- 【九度OJ】题目1475:IP数据包解析 解题报告
[九度OJ]题目1475:IP数据包解析 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1475 题目描述: 我们都学习过计算机网络, ...
- 【LeetCode】378. Kth Smallest Element in a Sorted Matrix 解题报告(Python)
[LeetCode]378. Kth Smallest Element in a Sorted Matrix 解题报告(Python) 标签: LeetCode 题目地址:https://leetco ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
随机推荐
- EEPROM
EEPROM (Electrically Erasable Programmable read only memory),带电可擦可编程只读存储器--一种掉电后数据不丢失的存储芯片. EEPROM 可 ...
- 通俗易懂的来理解Iaas,Paas,SaaS
首先我们先来了解一下这几个单词的意思和完全的英文 Iaas:Infrastructure as a service 基础设施即服务 Paas:Platform as a service 平台 ...
- Arch更新时failed to prepare transaction
error: failed to prepare transaction (could not satisfy dependencies) :: ffmpeg2.8: installing x265 ...
- Session 常见操作
对于敏感.重要的信息,建议要存储在服务器端(Session是存储在服务器端的),不能存储在浏览器中,如用户名.余额.等级.验证码等信息 Session依赖于Cookie session数据的获取 se ...
- React之Perf
import Perf from 'react-addons-perf' // ES6语法 var Perf = require('react-addons-perf') // ES5语法针对node ...
- latex 双引号 “
别在latex敲,在记事本上敲完后,拷贝到latex中.
- bcftools或vcftools提取指定区段的vcf文件(extract specified position )
下载安装bcftools 见如下命令: bcftools filter 1000Genomes.vcf.gz --regions 9:4700000-4800000 > 4700000-4800 ...
- Day23--Python--常用模块02--序列化,configparser
1. 序列化 把对象打散成bytes或者字符串. 方便存储和传输 序列化 把bytes或者字符串转换回对象. 反序列化 2. pickle(比较重要) 把python中所有的对象都可以转化成bytes ...
- python学习笔记-Day2 Numpy数组
1. 实现两个数组相加,在数据量特别大的时候 产生数组: (1) 从列表产生数组:a=[0,1,2,3] a=np.array(1) a (2) 从列表传入 a=np.array([1,2,3,4 ...
- phpstudy vhosts.conf 文件配置 记录下!
<VirtualHost _default_:80>DocumentRoot "D:\phpStudy\WWW" <Directory "D:\phpS ...