Codeforces Round #578 (Div. 2) Solution
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的更多相关文章
- Codeforces Round #578 (Div. 2)
Codeforces Round #578 (Div. 2) 传送门 A. Hotelier 暴力即可. Code #include <bits/stdc++.h> using names ...
- Codeforces Round #466 (Div. 2) Solution
从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...
- 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution
对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...
- Codeforces Round #545 (Div. 1) Solution
人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...
- Codeforces Round 500 (Div 2) Solution
从这里开始 题目地址 瞎扯 Problem A Piles With Stones Problem B And Problem C Photo of The Sky Problem D Chemica ...
- Codeforces Round #607 (Div. 1) Solution
从这里开始 比赛目录 我又不太会 div 1 A? 我菜爆了... Problem A Cut and Paste 暴力模拟一下. Code #include <bits/stdc++.h> ...
- Codeforces Round #525 (Div. 2) Solution
A. Ehab and another construction problem Water. #include <bits/stdc++.h> using namespace std; ...
- Codeforces Round #520 (Div. 2) Solution
A. A Prank Solved. 题意: 给出一串数字,每个数字的范围是$[1, 1000]$,并且这个序列是递增的,求最多擦除掉多少个数字,使得别人一看就知道缺的数字是什么. 思路: 显然,如果 ...
- Codeforces Round #523 (Div. 2) Solution
A. Coins Water. #include <bits/stdc++.h> using namespace std; int n, s; int main() { while (sc ...
随机推荐
- (5.3)mysql高可用系列——mysql复制之复制的参数
参考:https://www.iteye.com/blog/shift-alt-ctrl-2269539 详情 [1]参数 #[1.1]基本参数 bind-address=192.168.1.201 ...
- java_实现一个类只能声明一个对象
public class StaticDemo { public int a=10; private static StaticDemo s= new StaticDemo(); private St ...
- # Pycharm打造高效Python IDE
Pycharm打造高效Python IDE 建议以scientific mode运行,在科学计算时,可以方便追踪变量变化,并且会提示函数的用法,比普通模式下的提示更加智能,一般在文件中引入了numpy ...
- eclipse+maven搭建springboot项目入门
一.下载jdk,例如(jdk1.8.171) 安装(注意仅仅安装jdk就可以了,不要安装jre,设置JAVA_HOME,配置jdk环境变量) 二.下载maven(apache-maven-3.5.3- ...
- HTML5-placeholder属性
HTML 5<input> placeholder属性 placeholder属性提供可描述输入字段预期值的提示信息(hint). 该提示会在输入字段为空时显示,并会在字段获得焦点时消失. ...
- 面向对象-this关键字的内存图解
/* 标准的代码改进版 this:哪个对象调用那个方法,this就代表那个对象 */ class Student { private String name; private int age; pub ...
- luogu P4755 Beautiful Pair
luogu 这题有坨区间最大值,考虑最值分治.分治时每次取出最大值,然后考虑统计跨过这个位置的区间答案,然后两边递归处理.如果之枚举左端点,因为最大值确定,右端点权值要满足\(a_r\le \frac ...
- 深入理解hadoop之机架感知
深入理解hadoop之机架感知 机架感知 hadoop的replication为3,机架感知的策略为: 第一个block副本放在和client所在的datanode里(如果client不在集群范围内, ...
- Three.js类似于波浪的效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- WinRAR去广告
许多解压软件的广告看着令人头疼,今天我就给大家分享一个把WinRAR软件的广告去掉的方法. 环境: win rar restorator 2007(腾讯软件直接下载即可) 步骤: 首先 ...