Problem A Hotelier

直接模拟即可~~

复杂度是$O(10 \times n)$

# include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
char s[N];
bool a[];
int main()
{
int n; scanf("%d",&n); scanf("%s",s);
for (int i=;i<n;i++) {
if (s[i]=='L') {
for (int j=;j<=;j++)
if (!a[j]) { a[j]=true; break;}
} else if (s[i]=='R') {
for (int j=;j>=;j--)
if (!a[j]) { a[j]=true; break;}
} else a[s[i]-'']=;
}
for (int i=;i<=;i++) printf("%d",a[i]);
puts("");
return ;
}

A.cpp

Problem B Hotelier

注意到高度的限制是带绝对值的,化简为$H_{i+1} - k \leq H_i \leq H_{i+1}+k$

显然较高的限制是没有意义的,在一次最优的决策中不可能会选择当前从背包里面拿砖块去达到上界。

所以对于当前的决策来说,在保证仍然在高度下界以上,尽可能从地上拿砖块。

如果当前高度在高度下界以下,那么就需要从背包里拿出砖块使得到达高度下界。

注意到,地面的高度为$0$事实上,高度的下界是$\max\{H_{i+1} - k , 0\}$

复杂度是$O(T n)$

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=;
int n,m,k,h[N];
signed main()
{
int T; scanf("%lld",&T);
while (T--) {
scanf("%lld%lld%lld",&n,&m,&k);
for (int i=;i<=n;i++) scanf("%lld",&h[i]);
bool flag=true;
for (int i=;i<n;i++) {
int t=h[i]-max(h[i+]-k,0ll);
if (m+t>=) { m+=t; continue;}
else { flag=false; break;}
}
if (flag) puts("YES");else puts("NO");
}
return ;
}

B.cpp

Problem C Round Corridor

对于内部和外部的门,现在在一个连通块中是可以任意走动的,如果不在一个连通块中就不能。

对于图形可以划分成若干个连通块,当有重合的墙壁时会成为连通块的分界。第一个墙壁在12点钟方向已经重合。

非常明显接下来就是一个gcd类型的题目了。下面令$g = gcd(n,m)$

举例来说$[1,\frac{n}{g}] $和$[1,\frac{m}{g}]$ 是一个连通块.

形式化的说$[k \frac{n}{g}+1 , (k+1) \frac{n}{g}]$和$[k \frac{m}{g}+1 , (k+1) \frac{m}{g}] , k\in N $ 是一个连通块。

于是我们只需要判断如果在相同的连通块中就是"YES"否则就是"NO"

复杂度是$O(q)$

#include <bits/stdc++.h>
#define int long long
using namespace std; int n, m, q;
signed main()
{
cin >> n >> m >> q;
int lcmm = m / __gcd(n, m);
int lcmn = n / __gcd(n, m);
while (q --)
{
int sx, sy, ex, ey;
cin >> sx >> sy >> ex >> ey;
int p1 = , p2 = ;
if (sx == ) p1 = (sy + lcmn - ) / lcmn;
else p1 = (sy + lcmm - ) / lcmm;
if (ex == ) p2 = (ey + lcmn - ) / lcmn;
else p2 = (ey + lcmm - ) / lcmm;
if (p1 == p2) printf("YES\n");
else printf("NO\n");
}
}

C.cpp

Problem D White Lines

我们知道当前框的大小是不会发生变化的,对于一个左上角为$(i,j)$的正方形,覆盖到的范围是$(i,j) - (i+k-1,j+k-1)$

我们可以对行和列分别考虑,先考虑行,即求出在左上角为$(i,j)$的正方形点击,会造成多少行全是white。

对于每一行,我们记录最靠左黑点和最靠右白点的位置,只有覆盖这两个位置,该行才能被覆盖。

将已经全是白块的行忽略,这是因为无论怎么点击都是有贡献的。

首先可以暴力$O(k)$计算$(1,1)$的答案,于是问题转化为向下滑动这个$k\times k$的正方形来获取下一个答案。

在计算$(2,1) , (3,1)$等第一个安放的正方形的时候直接$O(k)$暴力计算,滑动一次判断进出的复杂度是$O(1)$的,

所以总复杂度是$O(n^2)$ 对于列的情况同理计算,答案就是同一位置两者之和的最大值。

# include<bits/stdc++.h>
using namespace std;
const int N=2e3+;
struct rec{
int l,r;
}c[N];
int a[N][N],n,k,ans[N][N];
char s[N];
int main()
{
scanf("%d%d",&n,&k);
for (int i=;i<=n;i++) {
scanf("%s",s+);
for (int j=;j<=n;j++)
if (s[j]=='B') a[i][j]=;
else a[i][j]=;
}
int ret=;
for (int i=;i<=n;i++) {
int l=n+,r=;
for (int j=;j<=n;j++)
if (a[i][j]==) l=min(l,j),r=max(r,j);
c[i].l=l; c[i].r=r;
if (c[i].r<c[i].l) ret++;
}
int rec=ret;
for (int j=;j<=n-k+;j++) {
for (int i=;i<=k;i++)
if (c[i].l<=c[i].r && j<=c[i].l&&c[i].r<=j+k-) ret++;
ans[][j]=ret;
for (int i=;i<=n-k+;i++) {
if (c[i-].l<=c[i-].r && j<=c[i-].l && c[i-].r<=j+k-) ret--;
if (c[i+k-].l<=c[i+k-].r && j<=c[i+k-].l && c[i+k-].r<=j+k-) ret++;
ans[i][j]=ret;
}
ret=rec;
}
ret=;
for (int j=;j<=n;j++) {
int l=n+,r=;
for (int i=;i<=n;i++)
if (a[i][j]==) l=min(l,i),r=max(r,i);
c[j].l=l; c[j].r=r;
if (c[j].r<c[j].l) ret++;
}
int res=; rec=ret;
for (int i=;i<=n-k+;i++) {
for (int j=;j<=k;j++)
if (c[j].l<=c[j].r && i<=c[j].l &&c[j].r<=i+k-) ret++;
res = max(res,ans[i][]+ret);
for (int j=;j<=n-k+;j++) {
if (c[j-].l<=c[j-].r && i<=c[j-].l && c[j-].r<=i+k-) ret--;
if (c[j+k-].l<=c[j+k-].r && i<=c[j+k-].l && c[j+k-].r <= i+k-) ret++;
res = max(res , ans[i][j]+ret);
}
ret=rec;
}
printf("%d\n",res);
return ;
}

D.cpp

Problem E Compress Words

可以使用双hash,然后题意不是两个相邻的单词合并,而是之前已经合并过的单词和下一个单词合并。

复杂度大概是$O(\sum |S_i|)$ ,其中$|S_i|$表示第$i$个单词的长度。

# include <cstdio>
# include <iostream>
# include <cstring>
# define hash Hash
# define e1 E1
# define e2 E2
# define mo1 MO1
# define mo2 MO2
# define int long long
using namespace std;
const int N=2e6+,e1=,e2=;
const int mo1=1e9+,mo2=;
int Pow1[N],Pow2[N];
string s1,s2;
int n;
struct StringHash{
pair<int,int> hash[N];
void build(string s) {
int len=s.length(); hash[]=make_pair(,);
for (int i=;i<=len;i++)
hash[i].first=(hash[i-].first*e1%mo1+s[i-])%mo1,
hash[i].second=(hash[i-].second*e2%mo2+s[i-])%mo2;
}
pair<int,int> gethash(int l,int r) {
pair<int,int>ans;
ans.first=((hash[r].first-Pow1[r-l+]*hash[l-].first%mo1)%mo1+mo1)%mo1;
ans.second=((hash[r].second-Pow2[r-l+]*hash[l-].second%mo2)%mo2+mo2)%mo2;
return ans;
}
}S,T;
void work()
{
int len1=s1.length(),len2=s2.length();
T.build(s2); int ans=;
for (int mid=;mid<=min(len1,len2);mid++)
if (S.gethash(len1-mid+,len1) == T.gethash(,mid)) ans=mid;
for (int i=ans;i<len2;i++) {
S.hash[i-ans++len1].first=(S.hash[i-ans+len1].first*e1%mo1+s2[i])%mo1,
S.hash[i-ans++len1].second=(S.hash[i-ans+len1].second*e2%mo2+s2[i])%mo2;
s1+=s2[i];
}
}
signed main() {
cin.sync_with_stdio(); cin.tie();
Pow1[]=Pow2[]=;
for (int i=;i<=;i++) Pow1[i]=Pow1[i-]*e1%mo1;
for (int i=;i<=;i++) Pow2[i]=Pow2[i-]*e2%mo2;
cin>>n; cin>>s1; S.build(s1);
for (int i=;i<=n;i++) {
cin>>s2; work();
}
cout<<s1;
return ;
}

E.cpp

Problem F White Lines

考虑到每个点的出度最大只有$10$。所以对于到达任意点的权$k$来说,只有$lcm(1..10) = 2520$种不同可能的后果。

所以所有权值$k$只需要在$mod 2520$的意义下计算就行。

记$ans[u][val]$表示当前到达顶点$u$当前带权为$val$的答案。

那么可以用记忆化搜索来维护这一条路径,然后用set来去重,就可以得到答案了。

由于每个点每个状态只可能访问一次,所以本题时间复杂度是$O(lcm(1..10) \times n)$

# include <bits/stdc++.h>
using namespace std;
const int N=,M=;
vector<int>E[N];
int k[N],ans[N][M],n;
bool vis[N][M];
pair<int,int>pre[N][M];
int dfs(int u,int val)
{
if (ans[u][val]) return ans[u][val];
vis[u][val]=;
int nex=(val+k[u])%;
int v=E[u][nex%E[u].size()];
if (ans[v][nex]) return ans[u][val]=ans[v][nex];
if (!vis[v][nex]) {
pre[v][nex]=make_pair(u,val);
return ans[u][val]=dfs(v,nex);
} else {
set<int>s;
pair<int,int> now = make_pair(u,val);
while (now!=make_pair(v,nex)) {
s.insert(now.first);
now=pre[now.first][now.second];
}
s.insert(now.first);
return ans[u][val]=s.size();
}
}
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d",&k[i]),k[i]=(k[i]%+)%;
for (int i=;i<=n;i++){
int t; scanf("%d",&t);
for (int j=;j<=t;j++) {
int v; scanf("%d",&v);
E[i].push_back(v);
}
}
int q; scanf("%d",&q);
while (q--) {
int x,y; scanf("%d%d",&x,&y);
printf("%d\n",dfs(x,(y%+)%));
}
return ;
}

F.cpp

Codeforces Round #578 (Div. 2) Solution的更多相关文章

  1. Codeforces Round #578 (Div. 2)

    Codeforces Round #578 (Div. 2) 传送门 A. Hotelier 暴力即可. Code #include <bits/stdc++.h> using names ...

  2. Codeforces Round #466 (Div. 2) Solution

    从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...

  3. 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution

    对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...

  4. Codeforces Round #545 (Div. 1) Solution

    人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...

  5. Codeforces Round 500 (Div 2) Solution

    从这里开始 题目地址 瞎扯 Problem A Piles With Stones Problem B And Problem C Photo of The Sky Problem D Chemica ...

  6. Codeforces Round #607 (Div. 1) Solution

    从这里开始 比赛目录 我又不太会 div 1 A? 我菜爆了... Problem A Cut and Paste 暴力模拟一下. Code #include <bits/stdc++.h> ...

  7. Codeforces Round #525 (Div. 2) Solution

    A. Ehab and another construction problem Water. #include <bits/stdc++.h> using namespace std; ...

  8. Codeforces Round #520 (Div. 2) Solution

    A. A Prank Solved. 题意: 给出一串数字,每个数字的范围是$[1, 1000]$,并且这个序列是递增的,求最多擦除掉多少个数字,使得别人一看就知道缺的数字是什么. 思路: 显然,如果 ...

  9. Codeforces Round #523 (Div. 2) Solution

    A. Coins Water. #include <bits/stdc++.h> using namespace std; int n, s; int main() { while (sc ...

随机推荐

  1. (5.12)mysql高可用系列——复制中的在线切换GTID模式/增加节点/删除节点

    目录 [0]需求 前提,已经假设好基于传统异步复制的主库和从库1. [0.1]传统异步切换成基于GTID的无损模式 [0.2]增加特殊要求的从库 [1]操作环境 [2]构建 复制->半同步复制 ...

  2. 设计模式:解释器模式(Interpreter)

    为人处事是一门大学问,察言观色.听懂弦外之音都是非常重要的,老板跟你说“XX你最近表现平平啊,还得要多努力”,如果你不当回事,平常对待,可能下次就是“XX,恩,你人还是不错,平常工作也很努力,但是我想 ...

  3. # Excel批量处理数据

    Excel批量处理数据 拖住框下拉即可得到每行+3的结果

  4. Centos7 更换为网易YUM源

    当我们刚刚安装系统的时候 yum 的速度那是真滴慢所以我们就需要一个更加快速的镜像,这时候网易镜像带给我们便捷.下面来一起更换吧! 备份当前的 yum 源 # yum 源在目录 /etc/yum.re ...

  5. 一些通用的js工具类,添加自定义插件

    common_t.js /** * 通用工具组件 对原有的工具进行封装,自定义某方法统一处理<br> * ^_^ * * Author: em.D * Date: 2016-05-17 * ...

  6. MySQL数据库基础-JAVA

    数据库 MySQL初步 MySQL基础认知 (Oracle真的是走哪祸害到哪23333) Java多用MySQL和Oracle SQLServer也收费,但是还行,比Oracle便宜,一个差不多3w多 ...

  7. O009、KVM 网络虚拟化基础

    参考https://www.cnblogs.com/CloudMan6/p/5289590.html   网络虚拟化是虚拟化技术中最复杂的部分,学习难度最大.   但因为网络是虚拟化中非常重要的资源, ...

  8. 干货分享!Oracle 的入门到精通 ~

    Oracle Database,又名Oracle RDBMS,或简称Oracle.是甲骨文公司的一款关系数据库管理系统.它是在数据库领域一直处于领先地位的产品.可以说Oracle数据库系统是目前世界上 ...

  9. 89. Gray Code (Java)

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  10. LaTeX的tasks宏包

    tasks 宏包 LaTeX的列表(list)通常是将项(item,条目)一个一个垂直的平行显示,所谓"列"表的由来. 水平分列列表,即将多个项分散到各列而不是一列,在出考卷的选择 ...