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个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 任务:对于给定 ...
随机推荐
- UI界面之淡入淡出
1.using UnityEngine; using System.Collections; using UnityEngine.UI; public class danrudanchu : Mono ...
- C#日期格式字符串的相互转换
方法一:Convert.ToDateTime(string) string格式有要求,必须是yyyy-MM-dd hh:mm:ss ================================== ...
- VS编译后直接复制DLL库文件到其他目录下
项目目录:SourceCode\公共组件\KApiClient\ 要复制的目的目录: SourceCode\公共组件\DllLibrary\ApiClient 则在项目 KApiClient下添加如下 ...
- JS实例3
window.setInterval("Time()",1); function Time() { var date = new Date();//当前时间函数 var n = d ...
- linux正则
正则表达式 分两类: 基本正则表达式:BRE 扩展正则表达式:ERE :grep -E, egrep 正则表达式引擎: 采用不同算法,检查处理正则表达式的软件模块 PCRE(Perl ...
- django 设置不带后缀的访问路径
在urls.py 设置空路径,并指向对应的html文件 url(r'^$', views.index),
- v1版本
<?php use yii\helpers\Html; use yii\helpers\Url; use yii\widgets\DetailView; use yii\grid\GridVie ...
- clientWidth,offsetWidth,scrollWidth区别
<html> <head> <title>clientWidth,offsetWidth,scrollWidth区别</title> </head ...
- python XML文件解析:用ElementTree解析XML
Python标准库中,提供了ET的两种实现.一个是纯Python实现的xml.etree.ElementTree,另一个是速度更快的C语言实现xml.etree.cElementTree.请记住始终使 ...
- Java Socket入门
Java Socket底层采用TCP/IP协议通信,通信细节被封装,我们仅仅需要指定IP.端口,便能轻易地创建TCP或UDP连接,进行网络通信.数据的读写,可以使用我们熟悉的stream进行操作. T ...