CF1169(div2)题解报告

A

不管

B

首先可以证明,如果存在解

其中必定有一个数的出现次数大于等于\(\frac{m}{2}\)

暴力枚举所有出现次数大于等于$\frac{m}{2} $的数

剩下的数看看有没有一个公共数即可

由于出现次数大于等于$\frac{m}{2} $的数不会太多

所以时间复杂度应该是\(O(n)\)的

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
const int N = 3e5 + 3;
int n,r;LL ans;
char s[N];
int main(){
scanf("%s",s + 1);
n = strlen(s + 1);
r = n + 1;
for(int i = n - 1;i >= 1;--i){
r = min(r,i + 9);
for(int k = 1;i + 2 * k <= r;++k){
if(s[i] == s[i + k] && s[i] == s[i + k + k]){
r = min(r,i + k + k);
break;
}
}
ans += n - r + 1;
}
cout << ans;
return 0;
}

C

所有题目先考虑答案是否就有单调性

这种最优解问题且答案具有单调性的题目先考虑二分答案

然后看卡能否贪心判断可行性

这道题我们二分枚举答案之后

我们肯定是贪心的让每个数都尽量小

对于一个数

如果他能在二分的答案的步数之内达到最小值就去

如果不行看看是否合法,判断一下是否无解

因为我们肯定不会让一个满足条件数再变大,那样只会不优

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 3e5 + 3;
int a[N];
int f[N];
int pre[N];
int n,m;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int ans = 0x3f3f3f3f;
inline bool check(int mid){
for(int i = 1;i <= n;++i) pre[i] = a[i];
pre[1] = m - a[1] > mid ? a[1] : 0;
for(int i = 2;i <= n;++i){
if(a[i] < pre[i - 1]){
if(pre[i - 1] > a[i] + mid) return 0;
pre[i] = pre[i - 1];
}
else{
if(a[i] == pre[i - 1]) pre[i] = a[i];
if(a[i] > pre[i - 1]) pre[i] = m - a[i] + pre[i - 1] > mid ? a[i] : pre[i - 1];
}
}
return 1;
}
int main(){
n = read(),m = read();
for(int i = 1;i <= n;++i) a[i] = read();
int l = 0,r = 10000000,ans;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid)) r = mid - 1,ans = mid;
else l = mid + 1;
}
cout << ans;
return 0;
}

D

神仙暴力题Orz

自己搞一棵01Trie试一试,发现长度为\(9\)或者以上的区间一定会满足题目中的要求

那么我们对于每一个固定的左端点\(l\)

我们都找一个离它的最近的满足条件的\(r\), \(r\in[l,l+9]\)

那么右端点\([r,n]\)都是合法的

在枚举的时候我们发现

对于一个\(l\),\(l + 1\)的满足条件的最近端点一定在\(l\)的满足条件的最右端点的左边

因为\([l+r,r_{l + 1}]\)也在\(l\)包含的区间内

所以我们每一次都继承\(l +_1\)的答案

看看能否继续变优

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
const int N = 3e5 + 3;
int n,r;LL ans;
char s[N];
int main(){
scanf("%s",s + 1);
n = strlen(s + 1);
r = n + 1;
for(int i = n - 1;i >= 1;--i){
r = min(r,i + 9);
for(int k = 1;i + 2 * k <= r;++k){
if(s[i] == s[i + k] && s[i] == s[i + k + k]){
r = min(r,i + k + k);
break;
}
}
ans += n - r + 1;
}
cout << ans;
return 0;
}

E

这道题是真的没思路

我们可以写一个\(n^2\)的代码

bool check(int x,int y){
int v1 = a[x];
for(int i = x + 1;i < y;++i)
if(v1 & a[i]) v1 |= a[i];
return v1 & a[y];
}

就是说我们考虑当前的子集

如果这个点能够和某一个元素连边

他一定可以从\(x\)转移过来

那么我们就分位考虑

在线段树上维护这个东西

每个节点维护\(19\)个变量

表示包含\(2^k\)的集合从左边传过来,最终会变成什么样

	inline void pushup(int u){
for(int i = 0;i < 19;++i){
int v = a[a[u].lc].sum[i];
a[u].sum[i] = v;
for(int j = 0;j < 19;++j)
if(v & (1 << j)) a[u].sum[i] |= a[a[u].rc].sum[j];
a[u].sum[i] |= a[a[u].rc].sum[i];
}
}

pushup大约这么写,注意这里有一个细节,就是我们判断左边是否有这一位的时候

应该用原来的值(我代码中的\(v\))判断,而不能够用更新之后的\(a[u].sum[i]\)去判断

这样很明显会错,会引入不合法的情况

查阅答案就和这个类似了

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 3e5 + 3;
int b[N];
int n,q,rt;
int ans;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
struct tree{
struct node{
int lc;
int rc;
int sum[21];
}a[N << 1];
int t;
inline void pushup(int u){
for(int i = 0;i < 19;++i){
int v = a[a[u].lc].sum[i];
a[u].sum[i] = v;
for(int j = 0;j < 19;++j)
if(v & (1 << j)) a[u].sum[i] |= a[a[u].rc].sum[j];
a[u].sum[i] |= a[a[u].rc].sum[i];
}
}
inline void build(int &u,int l,int r){
if(!u) u = ++t;
if(l == r){
for(int i = 0;i < 19;++i)
if(b[l] & (1 << i)) a[u].sum[i] = b[l];
return ;
}
int mid = (l + r) >> 1;
build(a[u].lc,l,mid);build(a[u].rc,mid + 1,r);
pushup(u);
}
inline bool query(int u,int l,int r,int ll,int rr,int w){
if(ans & w) return 1;
if(ll > rr) return 0;
if(l == ll && r == rr){
int v = 0;
for(int i = 0;i < 19;++i) if(ans & (1 << i)) v |= a[u].sum[i];
ans |= v;
return ans & w;
}
int mid = (l + r) >> 1;
if(rr <= mid) return query(a[u].lc,l,mid,ll,rr,w);
else if(ll > mid) return query(a[u].rc,mid + 1,r,ll,rr,w);
else return query(a[u].lc,l,mid,ll,mid,w) | query(a[u].rc,mid + 1,r,mid + 1,rr,w);
}
}T;
int main(){
// system("pause");
n = read(),q = read();
for(int i = 1;i <= n;++i) b[i] = read();
T.build(rt,1,n);
for(int i = 1;i <= q;++i){
int x = read(),y = read();
if(x == 0 || y == 0) printf("Fou\n");
else{
// if(x == y) printf("Shi\n");
// else {
ans = b[x];
if(T.query(rt,1,n,x + 1,y - 1,b[y])) printf("Shi\n");
else printf("Fou\n");
// }
}
}
// system("pause");
return 0;
}

这样的时间复杂度为\(O(nlog^2(n))\)

听说这道题一个log的DP做法,先咕一咕

CF1169(div2)题解报告的更多相关文章

  1. CF Educational Round 78 (Div2)题解报告A~E

    CF Educational Round 78 (Div2)题解报告A~E A:Two Rival Students​ 依题意模拟即可 #include<bits/stdc++.h> us ...

  2. CF Round #580(div2)题解报告

    CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...

  3. 2015浙江财经大学ACM有奖周赛(一) 题解报告

    2015浙江财经大学ACM有奖周赛(一) 题解报告 命题:丽丽&&黑鸡 这是命题者原话. 题目涉及的知识面比较广泛,有深度优先搜索.广度优先搜索.数学题.几何题.贪心算法.枚举.二进制 ...

  4. cojs 强连通图计数1-2 题解报告

    OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一 ...

  5. cojs 二分图计数问题1-3 题解报告

    OwO 良心的FFT练手题,包含了所有的多项式基本运算呢 其中一部分解法参考了myy的uoj的blog 二分图计数 1: 实际是求所有图的二分图染色方案和 我们不妨枚举这个图中有多少个黑点 在n个点中 ...

  6. 题解报告:hdu 1398 Square Coins(母函数或dp)

    Problem Description People in Silverland use square coins. Not only they have square shapes but also ...

  7. 题解报告:hdu 2069 Coin Change(暴力orDP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2069 Problem Description Suppose there are 5 types of ...

  8. 题解报告:hdu 1028 Ignatius and the Princess III(母函数or计数DP)

    Problem Description "Well, it seems the first problem is too easy. I will let you know how fool ...

  9. CFEducational Codeforces Round 66题解报告

    CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第 ...

随机推荐

  1. JavaScript--微博发布效果

    效果图: 实现思路:  当发布按钮被点击时,又会分为三种情况 1.如果输入的内容为空,弹出提示:不能发布空微博 2.如果输入的文字超过120,弹出提示,微博内容不能超过120 3.正常发布微博到列表里 ...

  2. Oracle使用——impdp导入数据时数据表已经存在

    背景 在做数据迁移时,需要将不同地方的dmp文件整合到一个数据库中,在导入时,目标表已经存在,该如何把数据追加进入目标表中 方法介绍 当使用IMPDP完成数据库导入时,如遇到表已存在时,Oracle提 ...

  3. hdu5438 dfs+并查集 长春网赛

    先dfs对度小于2的删边,知道不能删为止. 然后通过并查集来计算每一个分量里面几个元素. #include<iostream> #include<cstring> #inclu ...

  4. hdu1564 简单博弈

    多画几个图可以发现规律: #include<stdio.h> int main() { int i,n; while(scanf("%d",&n)!=EOF) ...

  5. cocos2dx 2.2.3在Windows 7 64bit上搭建开发环境

    最终弄完了cocos2dx 2.2.3在windows 7 64bit上的环境搭建,过程比較揪心.揪心的主要原因还是引擎的开发人员和官方文档的写作者都是偏爱MAC OS的,所以官方文档中的安装方法是以 ...

  6. python ASCII编码集

  7. 巨蟒python全栈开发-第11阶段 ansible_project4

    1.主机的增删改查 2.初始化的增删改查 3.项目的增删改查

  8. 当better-scroll遇见了react擦出的火花

    关于better-scroll这个插件前面已经介绍过两次了 从原生js使用到结合服务端发送数据使用都有过介绍 今天给大家分享一下这款插件在react中遇见的坑  总之我真是对这款插件又爱又恨 每次各种 ...

  9. MySQL列出当前月的每一天

    因为工作的原因,要用MySQL列出当前月份每一天的日期,自己查了下网上资料都是列出最近一个月的日期的解决方案,自己根据查到的的方案,修改成了下面两个方案,在此记录下: 方案一: SELECT date ...

  10. oracle函数 REPLACE(c1,c2[,c3])

    [功能]将字符表达式值中,部分相同字符串,替换成新的字符串 [参数] c1   希望被替换的字符或变量 c2   被替换的字符串 c3   要替换的字符串,默认为空(即删除之意,不是空格) [返回]字 ...