noip模拟题 2017.10.28 -kmp -Tarjan -鬼畜的优化

题目大意 给定A串,选择A串的前lB个字符作为B串,再在B串后增加一个字符,问最长的相等的A串前缀和B串的后缀。
Solution 1(KMP)
用1个奇怪的字符连接A串和B串,再用KMP求最长公共前后缀。
Solution 2(Hash)
hash A串的前缀和B的后缀,然后for去比较,取最大的相等的一个

题目大意 找出图上所有点,当它被删掉后使得1和n不连通。
因为这个点删掉后能够使1和n不在同一个联通块内,所以这个点一定是割点。
但是不是所有的割点都合法。当这个点被删掉后,如何判断1和n是否在同一联通块中?
考虑Tarjan,在Tarjan造出的dfs树上,枚举每个割点(除了点1和点n)
假设当前枚举的割点为点i,首先考虑是否点n在点i的子树中,如果不在,说明删掉点i后,1和n一定连通,
现在考虑点n在点i的子树中,但是否存在反祖边使得点n和点1所在联通块连通。
这个根据Tarjan的过程中记录的深度优先值和连向的最早的祖先的值可以很容易得到想到下面一个方法
枚举点i的所有子树,判断点n是否在这中间,如果在,再判断那个点的反祖边有没有连向点i的祖先。
Code
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include <cctype>
#include <ctime>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <map>
#include <set>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
typedef pair<int, int> pii;
#define smin(_a, _b) _a = min(_a, _b)
#define smax(_a, _b) _a = max(_a, _b)
#define fi first
#define sc second template<typename T>
inline boolean readInteger(T& u) {
static char x = ;
int flag = ;
if(x == -)
return false;
while(!isdigit(x = getchar()) && x != '-' && x != -);
if(x == -)
return false;
if(x == '-')
flag = -, x = getchar();
for(u = x - ''; isdigit(x = getchar()); u = u * + x - '');
u *= flag;
return true;
} const int N = 2e5 + ;
const int M = 4e5 + ; typedef class Edge {
public:
int end;
int next; Edge(int end = , int next = ):end(end), next(next) { }
}Edge; typedef class MapManager {
public:
int ce;
int h[N];
Edge edge[M << ]; MapManager() { }
MapManager(int n):ce() {
memset(h, , sizeof(int) * (n + ));
} void addEdge(int u, int v) {
edge[++ce] = Edge(v, h[u]);
h[u] = ce;
} void addDoubleEdge(int u, int v) {
addEdge(u, v);
addEdge(v, u);
} int start(int node) {
return h[node];
} Edge& operator [] (int pos) {
return edge[pos];
}
}MapManager; int n, m;
MapManager g; inline void init() {
readInteger(n);
readInteger(m);
g = MapManager(n);
for(int i = , u, v; i <= m; i++) {
readInteger(u);
readInteger(v);
g.addDoubleEdge(u, v);
}
} int cnt;
int brunch[N];
int dfn[N], ef[N];
boolean exists[N];
void tarjan(int node, int last) {
brunch[node] = ;
dfn[node] = ef[node] = ++cnt;
for(int i = g.start(node); i; i = g[i].next) {
int& e = g[i].end;
if(e == last) continue;
if(brunch[e] == -) {
tarjan(e, node);
brunch[node]++;
smin(ef[node], ef[e]);
exists[node] = exists[node] || exists[e];
} else {
smin(ef[node], dfn[e]);
}
}
// cerr << node << " " << dfn[node] << " " << ef[node] << endl;
} boolean check(int node) {
for(int i = g.start(node); i; i = g[i].next)
if(dfn[g[i].end] > dfn[node] && ef[g[i].end] < dfn[node] && exists[g[i].end])
return false;
return true;
} int top;
int lis[N];
inline void solve() {
cnt = ;
memset(brunch, -, sizeof(int) * (n + ));
memset(exists, false, sizeof(int) * (n + ));
exists[n] = true;
tarjan(, );
top = ;
for(int i = ; i < n; i++)
if(brunch[i] > && check(i) && exists[i])
lis[top++] = i;
printf("%d\n", top);
for(int i = ; i < top; i++)
printf("%d ", lis[i]);
putchar('\n');
} int T;
int main() {
freopen("home.in", "r", stdin);
freopen("home.out", "w", stdout);
readInteger(T);
while(T--) {
init();
solve();
}
return ;
}

题目大意 有n个球排成了一个环,球的颜色不是红色就是蓝色,每次操作可以交换相邻的两个球,问最少多少次操作可以使得所有同一种颜色的球都挨在一起。
显然是需要枚举的。
所以考虑枚举中间的位置,然后贪心地把一种颜色往两端塞。
然后会发现有一定单调性,故用两个队列维护一下扔左边的和扔右边的的球。
Code
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include <cctype>
#include <ctime>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <map>
#include <set>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
typedef pair<int, int> pii;
#define ll long long
#define smin(_a, _b) _a = min(_a, _b)
#define smax(_a, _b) _a = max(_a, _b)
#define fi first
#define sc second
const signed ll llf = (~0ll) >> ;
template<typename T>
inline boolean readInteger(T& u) {
static char x = ;
int flag = ;
if(x == -)
return false;
while(!isdigit(x = getchar()) && x != '-' && x != -);
if(x == -)
return false;
if(x == '-')
flag = -, x = getchar();
for(u = x - ''; isdigit(x = getchar()); u = u * + x - '');
u *= flag;
return true;
} const int N = 1e6 + ; int n;
deque<int> ql, qr;
char s[N]; inline void init() {
gets(s);
n = strlen(s);
} inline void solve() {
ll res = , cmp = ;
for(int i = ; i < n; i++)
if(s[i] == 'R')
cmp += i - (signed)qr.size(), qr.push_back(i);
int p, d1, d2;
while(!qr.empty()) {
p = qr.back();
d1 = p - (signed)qr.size() + ;
d2 = n - (signed)ql.size() - p - ;
if(d1 > d2) qr.pop_back(), ql.push_front(p), cmp += d2 - d1;
else break;
}
res = cmp; for(int i = , p, d1, d2; i < n; i++) {
boolean flag = false;
if(qr.front() < i) {
ql.push_back(qr.front());
qr.pop_front();
flag = true;
}
if(!flag) cmp += (signed)ql.size() - (signed)qr.size();
while(!ql.empty()) {
p = ql.front();
d1 = (p - (i + (signed)qr.size()) % n + n) % n;
d2 = ((i - (signed)ql.size() + n) % n - p + n) % n;
if(d1 < d2) ql.pop_front(), qr.push_back(p), cmp += d1 - d2;
else break;
}
smin(res, cmp);
}
printf(Auto"\n", res);
ql.clear();
qr.clear();
} int T;
int main() {
freopen("sushi.in", "r", stdin);
freopen("sushi.out", "w", stdout);
readInteger(T);
// gets(s);
while(T--) {
init();
solve();
}
return ;
}
noip模拟题 2017.10.28 -kmp -Tarjan -鬼畜的优化的更多相关文章
- NOIP模拟题 2017.11.6
题目大意 给定一个大小为n的数组,从中选出一个子集使得这个子集中的数的和能被n整除. 假设开始我没有做出来,那么我就random_shuffle一下,然后计算前缀和,有一个能被n整除,就输出答案.于是 ...
- NOIP模拟题 2017.7.3 - 模拟 - 贪心 - 记忆化搜索
直接暴力模拟,注意判数据结构为空时的取出操作. Code #include<iostream> #include<cstdio> #include<ctime> # ...
- 【NOIP模拟题】行动!行动!(spfa+优化)
spfa不加优化果断tle最后一个点................... 这题和ch的一题很像,只不过这题简单点,这是一个层次图,即有很多个相同的图,这些相同的图之间又存在着练习.. 然后每一次队列 ...
- NOIP模拟题汇总(加厚版)
\(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...
- 8.22 NOIP 模拟题
8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...
- 【入门OJ】2003: [Noip模拟题]寻找羔羊
这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...
- 9.9 NOIP模拟题
9.9 NOIP模拟题 T1 两个圆的面积求并 /* 计算圆的面积并 多个圆要用辛普森积分解决 这里只有两个,模拟计算就好 两圆相交时,面积并等于中间两个扇形面积减去两个三角形面积 余弦定理求角度,算 ...
- NOIP模拟题17.9.26
B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...
- noip模拟题题解集
最近做模拟题看到一些好的题及题解. 升格思想: 核电站问题 一个核电站有N个放核物质的坑,坑排列在一条直线上.如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 任务:对于给定 ...
随机推荐
- [转-SSRF]什么是SSRF
这些天专注了解了SSRF攻击(Server-side Request Forgery,服务器端请求伪造),对这类攻击有了自己的一些总结与看法,老外取这个名字是挺不错的,我很喜欢,这让我想到了CSRF( ...
- 5.JVM的内存区域划分
一.JVM介绍 1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟 ...
- Vue系列之 => 模拟购物车添加小球动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mysql按天,按周,按月,按季度,按年统计数据
/*查询2小时前的数据*/select * from tableName WHERE create_time HOUR) SELECT count(id) FROM rd_track_info WHE ...
- IOS 开发体验测试问题
1.键盘收起体验 a. 文本键盘会收起,但是表情包.添加视频的键盘不会收起: b. 在会话场景中,同时进行一个点击输入框,一个向下滑,输入框中的聚焦的竖直细线不会消失:
- python pymssql 连接数据库
1)写在前面 远程连接数据库的时候,端口前面都是用的逗号, 因为惯性思维, 就傻傻的把 ip+,+端口 赋值给server了,然后一直报错, pymssql.InterfaceError: Co ...
- flask模板应用-空白控制
模板应用实践 空白控制 在实际输出的HTML文件中,模板中的jinja2语句.表达式和注释会保留移除后的空行. 例如下面的代码: {% set user.age = 23 %} {% if urer. ...
- AWS免费云服务套餐申请步骤及常见问题
AWS免费云服务套餐申请步骤及常见问题 AWS免费使用套餐常见问题_AWS免费云服务套餐_-AWS云服务https://amazonaws-china.com/cn/free/faqs/ 什么是 AW ...
- 随笔 js-----------------------------------------------------------------------------------------------------
http://www.cnblogs.com/liuling/p/2014-4-19-04.html redis Base64.encode($( "#byerName").v ...
- Android Auto开发初探
一.Android Auto 概述 二.Android Auto 使用方法 四.Android Auto应用开发 五.Android Auto开发总结 一.Android Auto 概述 最近物联网是 ...