蒟蒻就切了四道水题,然后EF看着可写然而并不会,中间还WA了一次,我太菜了.jpg =。=

A.Vasya And Password

一开始看着有点虚没敢立刻写,后来写完第二题发现可以暴力讨论,因为保证有解,没了

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
char rd[N];
int main ()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",rd);
int c1=,c2=,c3=,len=strlen(rd);
for(int i=;i<len;i++)
{
if(rd[i]>=''&&rd[i]<='') c1++;
if(rd[i]>='A'&&rd[i]<='Z') c2++;
if(rd[i]>='a'&&rd[i]<='z') c3++;
}
if(!c1&&!c2&&c3)
rd[]='',rd[]='A';
else if(!c1&&c2&&!c3)
rd[]='',rd[]='a';
else if(c1&&!c2&&!c3)
rd[]='a',rd[]='A';
else if(c1&&c2&&!c3)
{
if(c1>)
{
for(int i=;i<len;i++)
if(rd[i]>=''&&rd[i]<='') {rd[i]='a';break;}
}
else if(c2>)
{
for(int i=;i<len;i++)
if(rd[i]>='A'&&rd[i]<='Z') {rd[i]='a';break;}
}
}
else if(c1&&!c2&&c3)
{
if(c1>)
{
for(int i=;i<len;i++)
if(rd[i]>=''&&rd[i]<='') {rd[i]='A';break;}
}
else if(c3>)
{
for(int i=;i<len;i++)
if(rd[i]>='a'&&rd[i]<='z') {rd[i]='A';break;}
}
}
else if(!c1&&c2&&c3)
{
if(c3>)
{
for(int i=;i<len;i++)
if(rd[i]>='a'&&rd[i]<='z') {rd[i]='';break;}
}
else if(c2>)
{
for(int i=;i<len;i++)
if(rd[i]>='A'&&rd[i]<='Z') {rd[i]='';break;}
}
}
for(int i=;i<len;i++) printf("%c",rd[i]); printf("\n");
}
return ;
}

B.Relatively Prime Pairs

想了一会一拍脑袋,这题\*\*这么水还想啥,输出相邻数字,没了

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long l,r;
int main ()
{
scanf("%lld%lld",&l,&r);
printf("YES\n");
for(long long i=l;i<=r;i+=)
printf("%lld %lld\n",i,i+);
return ;
}

C.Vasya and Multisets

需要稍微想一想的题,然而本质上还是个分类讨论

考虑每种数字出现不同次数带来的影响,出现一次的一定对一个集合有贡献,出现两次的怎么放都没有影响,出现三次及以上的可以令它对一个集合有贡献,也可以令它没有影响

所以首先除去所有出现两次的数(都丢给一个集合即可),然后看看出现一次的有奇数个还是偶数个。如果有奇数个且没有出现三次以上的则无解;如果有奇数个且有出现三次及以上的就先两两分开出现一次的,把剩下那个放在一个集合,出现三次及以上的一个数放一个在另一个集合,然后剩下的一股脑丢在一个集合里;如果有偶数个就两两分开然后剩下的直接丢在一个集合里

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
long long num[N],cnt[N];
char outp[N];
bool used[N];
long long n,und,ans,k;
int main ()
{
scanf("%lld",&n);
for(int i=;i<=n;i++)
scanf("%lld",&num[i]),cnt[num[i]]++;
for(int i=;i<=;i++)
if(cnt[i]==)
{
for(int j=;j<=n;j++)
if(num[j]==i) used[j]=,outp[j]='A';
}
else if(cnt[i]>=)
{
und++;
for(int j=;j<=n;j++)
if(num[j]==i) used[j]=;
}
// for(int i=1;i<=n;i++) printf("%c",outp[i]);
for(int i=;i<=n;i++) if(!used[i]) ans++,outp[i]=(k^=)?'A':'B';
if((ans&)&&!und) {printf("NO");return ;}
else
{
if((ans&)==)
{for(int i=;i<=n;i++) if(used[i]) outp[i]='A';
}
else
{
bool flag=true;
for(int i=;i<=n;i++) if(used[i]&&cnt[num[i]]!=)
{
if(flag)outp[i]='B',flag=false;
else outp[i]='A';
}
}
}
printf("YES\n");
for(int i=;i<=n;i++)
printf("%c",outp[i]);
return ;
}

D.Bicolorings

递推题,画图推式子即可

设$rec[i][j][0/1][0/1]$表示到第$i$列分出了$j$块,且第$i$列上面为白/黑,下面为白/黑的方案数,这样就足够递推了,讨论新加入的两块与之前的联通情况即可

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
const long long mod=;
long long rec[N][*N][][];
long long n,m;
int main ()
{
scanf("%lld%lld",&n,&m);
rec[][][][]=rec[][][][]=;
rec[][][][]=rec[][][][]=;
for(int i=;i<=n;i++)
for(int j=;j<=*i;j++)
{
rec[i][j][][]+=rec[i-][j][][]+rec[i-][j][][]+rec[i-][j][][]+rec[i-][j-][][];
rec[i][j][][]+=rec[i-][j][][]+rec[i-][j][][]+rec[i-][j][][]+rec[i-][j-][][];
rec[i][j][][]+=rec[i-][j][][]+rec[i-][j-][][]+rec[i-][j-][][]; if(j>=) rec[i][j][][]+=rec[i-][j-][][];
rec[i][j][][]+=rec[i-][j][][]+rec[i-][j-][][]+rec[i-][j-][][]; if(j>=) rec[i][j][][]+=rec[i-][j-][][];
rec[i][j][][]%=mod;rec[i][j][][]%=mod;rec[i][j][][]%=mod;rec[i][j][][]%=mod;
}
printf("%lld",(rec[n][m][][]+rec[n][m][][]+rec[n][m][][]+rec[n][m][][])%mod);
return ;
}

E.Vasya and Big Integers

看这个范围,显然是个线性DP题然而你是个不会做DP的鶸

看了看AC代码没看懂,先咕着,等官方题解=。=

哦官方题解我也没看懂,弃疗了

F.The Shortest Statement

题目并不难......

看出题人都特意提示了$m-n<=20$我居然还没做出来,我太菜了=。=

先随便跑一棵搜索树出来,对于指回祖先的边特殊记录下这些祖先,然后continue掉,单独把这些祖先拿出来预处理最短路,然后回答询问的时候除了在搜索树上求一个树上距离再考虑一下这些祖先到两点的最短路之和就行了

调试的时候持续石乐志,出了一堆**错误......

 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,K=;
struct a
{
int node;
long long dist;
};
bool operator < (a x,a y)
{
return x.dist>y.dist;
}
priority_queue<a> hp;
int p[N],noww[*N],goal[*N],mem[K];
int siz[N],dep[N],anc[N],imp[N],top[N];
long long val[*N],dis[N],diss[K][N];
int n,m,q,t1,t2,cnt,len,tot;
long long t3;
bool vis[N],bac[N];
void link(int f,int t,long long v)
{
noww[++cnt]=p[f],p[f]=cnt;
goal[cnt]=t,val[cnt]=v;
}
void DFS(int nde,int fth,int dth)
{//printf("%d->%d\n",fth,nde);
int tmp=;
siz[nde]=,anc[nde]=fth,dep[nde]=dth;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
if(dep[goal[i]])
{
if(dep[goal[i]]<dep[nde])
mem[++len]=goal[i];
continue;
}
dis[goal[i]]=dis[nde]+val[i];
DFS(goal[i],nde,dth+);
siz[nde]+=siz[goal[i]];
if(siz[goal[i]]>tmp)
tmp=siz[goal[i]],imp[nde]=goal[i];
}
}
void MARK(int nde,int tpp)
{
top[nde]=tpp;
if(imp[nde])
{
MARK(imp[nde],tpp);
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
if(dep[goal[i]]>dep[nde]) MARK(goal[i],goal[i]);
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y); x=anc[top[x]];
}
return dep[x]<dep[y]?x:y;
}
void Dijkstra(int nde,int typ)
{
memset(diss[typ],0x3f,sizeof diss[typ]);
memset(vis,,sizeof vis); diss[typ][nde]=; hp.push((a){nde,});
while(!hp.empty())
{
a tt=hp.top(); hp.pop(); int tn=tt.node;
if(vis[tn]) continue; vis[tn]=true;
for(int i=p[tn];i;i=noww[i])
if(diss[typ][goal[i]]>diss[typ][tn]+val[i])
{
diss[typ][goal[i]]=diss[typ][tn]+val[i];
hp.push((a){goal[i],diss[typ][goal[i]]});
}
}
}
long long getdis(int n1,int n2)
{
int lca=LCA(n1,n2);
return dis[n1]+dis[n2]-*dis[lca];
}
int main ()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%lld",&t1,&t2,&t3);
link(t1,t2,t3),link(t2,t1,t3);
}
DFS(,,); MARK(,);
sort(mem+,mem++len);
len=unique(mem+,mem++len)-mem-;
for(int i=;i<=len;i++) Dijkstra(mem[i],i);
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&t1,&t2);
long long ans=getdis(t1,t2);
for(int i=;i<=len;i++)
ans=min(ans,diss[i][t1]+diss[i][t2]);
printf("%lld\n",ans);
}
return ;
}

G.Distinctification

看了官方题解,大概了解是什么思路了,但是这题解真的挺抽象的=。=

我们假设这些$pair$已经按照$a$从小到大排好序,那么我们考虑分成若干段来处理这个问题,分割的标准就是这一段首尾的距离大于等于首尾之差,也就是说这一段需要通过操作$1$来变得合法,我们就将它们划成一段,来在段内处理问题。

那么段内如何处理呢?显然我们首先将它调整成合法的情况,然后应该在段内将$b$从大到小排序,这样进行操作$2$最优,那么我们就需要用一个数据结构来维护段的信息。最后当我们处理完了所有的段,我们还需要快速将它们合并。对于合并,我们检查新加进来的$pair$左右相邻的位置,看看是否有其他段的右/左端点,有就合成一段。主要思想大概就是这样,然后说一点具体实现

对于段内的统计,我们需要统计一段区间(权值)$(l,r)$的左边的总和乘上右边的数量,然后减掉一个前缀和,统计的部分可以用权值线段树来实现。然后对于段的维护可以使用并查集,最后是段的合并,因为用线段树维护,所以就用线段树合并做就(=。=?)好了

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,M=;
long long sum[M],val[M],fsum[N];
int node[N],siz[M],son[M][];
int e[N],a[N],b[N],aset[N];
long long n,c,cnt;
int finds(int x)
{
return x==aset[x]?x:aset[x]=finds(aset[x]);
}
void pushup(int nde)
{
int ls=son[nde][],rs=son[nde][];
sum[nde]=sum[ls]+sum[rs],siz[nde]=siz[ls]+siz[rs];
val[nde]=val[ls]+val[rs]+1ll*sum[ls]*siz[rs];
}
void Create(int &nde,int l,int r,int pos,int task)
{
if(!nde) nde=++cnt;
if(l==r)
siz[nde]=,sum[nde]=val[nde]=task;
else
{
int mid=(l+r)/;
if(pos<=mid) Create(son[nde][],l,mid,pos,task);
else Create(son[nde][],mid+,r,pos,task); pushup(nde);
}
}
int Merge(int x,int y)//线段树合并
{
if(!x||!y) return x|y; int tmp=x;
son[tmp][]=Merge(son[x][],son[y][]);
son[tmp][]=Merge(son[x][],son[y][]);
if(!son[tmp][]&&!son[tmp][])
{
val[tmp]=val[x]+val[y]+1ll*sum[y]*siz[x];
sum[tmp]=sum[x]+sum[y];
siz[tmp]=siz[x]+siz[y];
}
else pushup(tmp);
return tmp;
}
long long query(int nde)
{
int nd=node[nde];
return val[nd]+1ll*(nde-)*sum[nd];
}
void gather(int a,int b)
{
int f1=finds(a),f2=finds(b);//合并两段
aset[f2]=f1,c-=query(f1),c-=query(f2);
node[f1]=Merge(node[f1],node[f2]),c+=query(f1);
}
int main ()
{
scanf("%lld",&n);
for(int i=;i<=;i++) aset[i]=i;
for(int i=;i<=n;i++)
{
scanf("%d%d",&a[i],&b[i]);
fsum[i]=fsum[i-]+1ll*a[i]*b[i];//预处理前缀和
a[i]=finds(a[i]),aset[a[i]]=a[i]+;//并查集维护段的情况
Create(node[a[i]],,,b[i],b[i]);
}
for(int i=;i<=;i++) aset[i]=i;
for(int i=;i<=n;i++)
{
c+=query(a[i]);
if(e[a[i]+]) gather(a[i],a[i]+);//检查左右是否有段
if(e[a[i]-]) gather(a[i]-,a[i]);
e[a[i]]=true,printf("%lld\n",c-fsum[i]);
}
return ;
}

2018.9.20 Educational Codeforces Round 51的更多相关文章

  1. Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)

    https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...

  2. Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)

    题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...

  3. Educational Codeforces Round 51 D. Bicolorings(dp)

    https://codeforces.com/contest/1051/problem/D 题意 一个2*n的矩阵,你可以用黑白格子去填充他,求联通块数目等于k的方案数,答案%998244353. 思 ...

  4. CodeForces Educational Codeforces Round 51 (Rated for Div. 2)

    A:Vasya And Password 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen(&q ...

  5. The Shortest Statement(Educational Codeforces Round 51 (Rated for Div.2)+最短路+LCA+最小生成树)

    题目链接 传送门 题面 题意 给你一张有\(n\)个点\(m\)条边的联通图(其中\(m\leq n+20)\),\(q\)次查询,每次询问\(u\)与\(v\)之间的最短路. 思路 由于边数最多只比 ...

  6. Educational Codeforces Round 51 (Rated for Div. 2) F - The Shortest Statement 倍增LCA + 最短路

    F - The Shortest Statement emmm, 比赛的时候没有想到如何利用非树边. 其实感觉很简单.. 对于一个询问答案分为两部分求: 第一部分:只经过树边,用倍增就能求出来啦. 第 ...

  7. Educational Codeforces Round 51 (Rated for Div. 2)

    做了四个题.. A. Vasya And Password 直接特判即可,,为啥泥萌都说难写,,,, 这个子串实际上是忽悠人的,因为每次改一个字符就可以 我靠我居然被hack了???? %……& ...

  8. Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement

    题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...

  9. 【 Educational Codeforces Round 51 (Rated for Div. 2) F】The Shortest Statement

    [链接] 我是链接,点我呀:) [题意] [题解] 先处理出来任意一棵树. 然后把不是树上的边处理出来 对于每一条非树边的点(最多21*2个点) 在原图上,做dijkstra 这样就能处理出来这些非树 ...

随机推荐

  1. CocoStuff—基于Deeplab训练数据的标定工具【三、标注工具的使用】

    一.说明 本文为系列博客第三篇,主要展示COCO-Stuff 10K标注工具的使用过程及效果. 本文叙述的步骤默认在完成系列文章[二]的一些下载数据集.生成超像素处理文件的步骤,如果过程中有提示缺少那 ...

  2. centos下设置自启动和配置环境变量的方法

    1. 设置自启动 在CentOS系统下,主要有两种方法设置自己安装的程序开机启动.1.把启动程序的命令添加到/etc/rc.d/rc.local文件中,比如下面的是设置开机启动httpd. #!/bi ...

  3. 20172308 实验二《Java面向对象程序设计 》实验报告

    20172308 2017-2018-2 <程序设计与数据结构>实验2报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 周亚杰 学号:20172308 实验教师:王 ...

  4. Structs2笔记①--structs的背景、structs2框架的意义、第一个helloworld

    Struts2的背景 由出色稳定的框架struts1和webwork框架整合而来的 吸取了两大框架的优点 提高了开发的效率和规范性 更好的实现了MVC架构 解除了与servlet的强耦合性 使用str ...

  5. 校园跳蚤市场-Sprint计划(第二阶段)

  6. bubble_sort(归并排序)

    ★实验任务 给定一个 1~N 的排列 P,即 1 到 N 中的每个数在 P 都只出现一次. 现在要 对排列 P 进行冒泡排序,代码如下: for (int i = 1; i <= N; ++i) ...

  7. struts2的运行原理以及底层的工作机制

    1 请求,请求路径是/login(发起请求,被filter拦截) 2 DispatcherFilter 3 获取当前请求的路径 通过request对象 request.getServletPath 4 ...

  8. tomcat介绍

    Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由java语言编写,需要运行在jvm虚拟机中.之所以Java的应用 ...

  9. jsp 页面和 jsp标记

    一个jsp页面可由5种元素组成 html标记 变量和方法的声明 java程序片 java表达式 <%!变量和方法的声明%> 被声明的方法和变量在整个jsp页面都可以访问,为全局变量 当多个 ...

  10. SQLSERVER 升级版本的方法

    1. 以SQLSERVER2014为例说明 SQLSERVER升级版本的方法, 也适用于evaluation 版本超过180天之后的处理. 2. 打开所有的应用 看到有一个 sqlserver2008 ...