T1 园艺工人的求助

【题目描述】
终于,在一段繁忙的训练之后,到了NOIP 的举办的时候。同学们坐上了大巴车,享受着沿途的风光,讨论着未解决的问题,憧憬着NOIP 赛场上切题的样子。很快,大
巴车到了大连大学科技楼,也就是辽宁NOIP 的举办地点。大连大学科技楼是一幢宏伟的建筑,楼前摆放有一排花,共有n 盆。花一共只有26 种,分别用26 个小写英文
字母表示,也就是说,楼前的这排花可以用一个仅包含小写英文字母的字符串表示。大连大学雇了一个园艺工人,专门打理科技楼前的花。园艺工人看见你,热情地向你打招呼:“NOIP 加油!”其实,他是有问题想请你帮忙呢!现在园艺工人想再购买一盆花(可以任选26 种花中的一种),插入到原来的花中间(可以放在整排花的最左侧与最右侧),他想知道在插入一盆花后,能否使整排花左右对称。例如,ababa 是左右对称的,而abcd 不是。注意:即使原来的一排花已经是左右对称的,也必须再插入一盆花。

【输入格式】
从文件flower.in 中读入数据。
本题目有多组数据,输入第一行为一个正整数t,表示数据组数。
接下来t 行,每行包含一个正整数n 和一个长度为n 的字符串,分别表示花的数量与花构成的序列。

【输出格式】
输出到文件flower.out 中。
对于每组数据输出一行。若再插入一盆花之后能使整排花左右对称,输出Yes,否则输出No(注意大小写)。

【样例1 输入】
4
4 abcd
4 aabb
4 aaaa
10 abcdefecba

【样例1 输出】
No
No
Yes
Yes

【子任务】
对于20% 的数据,n <= 5;
对于另30% 的数据,t = 1 且n <= 1000;
对于100% 的数据,Σn <= 106

题面好像就最后两句话有用。

就是说给一个字符串,再插入一个字符后能否成为一个回文串。

首先,如果他是回文串,那么插入一个字符后一定还是回文串,这个想想就明白了。

如果不是回文串,因为Σn <= 10 6,所以对于每一个字符串,我们暴力的从头L和尾R两个端点开始一个一个比对就行。然后遇到一个不一样的字符,我们需要考虑是往L那一端插入字符还是往R端插,分情况讨论即可,然后如果两种方案都又遇到不相等的字符,就输出No了,而其中一种方案成立,就Yes。

代码实现时,插入字符可以理解为这一端的指针向前跳一个字符。

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter printf("\n")
#define space printf(" ")
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const int eps = 1e-;
const int maxn = 1e6 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int t;
char a[maxn]; int main()
{
freopen("flower.in", "r", stdin);
freopen("flower.out", "w", stdout);
t = read();
while(t--)
{
int n = read(); scanf("%s", a + );
int cnt = ;
for(int i = , j = n; i < j; ++i, --j)
{
if(a[i] != a[j])
{
j++; cnt++;
if(cnt > ) break;
}
}
if(cnt < ) {printf("Yes\n"); continue;}
cnt = ;
for(int i = , j = n; i < j; ++i, --j)
{
if(a[i] != a[j])
{
i--; cnt++;
if(cnt > ) break;
}
}
printf("%s\n", cnt < ? "Yes" : "No");
}
return ;
}

T2 主席的请求

【题目描述】
再大连大学园艺工人的祝福下,你顺利地结束了NOIP 第一天的比赛。走出考场,漫步于大连大学美丽而静谧的校园中,你感到心情无比舒畅。正当你向大连大学宾馆走
去的时候,一个陌生人叫住了你。原来他是大连大学校园规划部主席,他早知道你是一个无所不能的OIer,并且尤其擅长道路规划。他向你请教了一个问题,希望你能给出答案。
大连大学可以看做一个由n 个结点,m 条有向道路构成的有向图。结点编号为1到n,每条道路有一个长度(为正整数)。其中,科技楼在s 号结点,大连大学宾馆在t
号结点。主席想知道,校园中的每条道路是否一定出现在从s 到t 的最短路径上,如果不一定,那么至少要将这条道路的长度减少多少,才能使这条道路一定出现在从s 到t的最短路径上(减少后的长度必须为一个正整数)。
【输入格式】
从文件road.in 中读入数据。
输入第一行包含4 个正整数n, m, s, t (n <= 2 * 105, m <= 4 * 105, 1 <= s, t <= n),含义如题。
接下来m 行,每行3 个正整数u, v, w(1 <= u, v <= n, w > 0),分别表示一条边的起点、终点、长度。
保证从s 能到达t。
【输出格式】
输出到文件road.out 中。
输出m 行。每行代表一条边的答案:
• 若该边一定出现在从s 到t 的最短路上,输出YES;
• 若该边不一定出现在从s 到t 的最短路上,但能通过改变该边长度为一正整数,使得该边一定出现在从s 至t 的最短路上,输出CAN 和一个正整数,用一个空格隔开,其中的正整数表示该边长度减少的最小值;
• 否则,输出NO。
【样例1 输入】

6 7 1 6

1 2 2
1 3 10
2 3 7
2 4 8
3 5 3
4 5 2
5 6 1

【样例1 输出】
YES
CAN 2
CAN 1
CAN 1
CAN 1
CAN 1
YES
【样例2 输入】
2 2 1 2
1 2 1
1 2 2
【样例2 输出】
YES
NO
【子任务】
对于15% 的数据,n = 5,m <=10;
对于另10% 的数据,整个图是一条链,即1 向2 连边,2 向3 连边,. . . . . . ,n - 1向n 连边,有且仅有这样的测试点n ≡ 9 (mod 10);
对于另20% 的数据,整个图是一棵有根树,其中s 是根,所有边由父节点指向子结点,有且仅有这样的测试点n ≡ 8 (mod 10);
对于另25% 的数据,n <= 1000,m <= 2000。

首先我们考虑每一条边,如果他一定在最短路上,就输出YES;如果可能在最短路上,那只要-1就一定是在最短路上了;如果不在最短路上,那我们只要让这条边变小,直到经过这条边的最短路径成为新的最短路就行了。

那么我们下面具体考虑怎么实现:

首先解决他是否在最短路上,只要正着跑一遍dijkstra然后反着跑一遍dijkstra就行了。正着跑得到dis1[i]表示起点 s 到 i 的最短路,同理dis2[i]表示终点t到 i 的最短路。那么经过从u到v的一条边的最短路就可以表示为dis1[u] + w + dis2[v],如果他和dis1[t],即最短路相等,那么他就可能在最短路上,否则一定不在。

接下来要判断的是w这条边是一定在最短路上还是可能在最短路上。首先我们得会最短路计数,参见我的另一篇博文,如果num1[u] * num2[v] == num1[t](总最短路条数)的话,就说明一定在图的最短路上了。

这样每一种情况就解决了。

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter printf("\n")
#define space printf(" ")
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const ll INF = 0x3f3f3f3f;
const int eps = 1e-;
const int maxn = 4e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int n, m, s, t;
struct Node
{
int x, y; ll c;
}a[maxn]; vector<ll> v[maxn], c[maxn], v2[maxn], c2[maxn]; ll dis[][maxn];
ll num[][maxn];
bool vis[maxn];
struct Dij //用pair看起来更简洁
{
int num; ll cost;
bool operator < (const Dij& other)const
{
return cost > other.cost || (cost == other.cost && num > other.num);
}
};
void dijkstra(int x, int p)
{
for(int i = ; i <= n; ++i) dis[p][i] = INF * INF;
Mem(vis);
priority_queue<Dij> q;
q.push((Dij){x, });
dis[p][x] = ; num[p][x] = ;
while(!q.empty())
{
Dij node = q.top(); q.pop();
int now = node.num;
if(vis[now]) continue;
vis[now] = ;
for(int i = ; i < (int)v[now].size(); ++i)
{
if(dis[p][now] + c[now][i] < dis[p][v[now][i]])
{
dis[p][v[now][i]] = dis[p][now] + c[now][i];
num[p][v[now][i]] = num[p][now];
q.push((Dij){v[now][i], dis[p][v[now][i]]});
}
else if(dis[p][now] + c[now][i] == dis[p][v[now][i]]) num[p][v[now][i]] += num[p][now];
}
}
} ll ans[maxn]; int main()
{
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
n = read(); m = read(); s = read(); t = read();
for(int i = ; i <= m; ++i)
{
a[i].x = read(); a[i].y = read(); a[i].c = read();
v[a[i].x].push_back(a[i].y);
c[a[i].x].push_back(a[i].c);
}
dijkstra(s, );
for(int i = ; i <= n; ++i) {v[i].clear(); c[i].clear();}
for(int i = ; i <= m; ++i)
{
v[a[i].y].push_back(a[i].x);
c[a[i].y].push_back(a[i].c);
}
dijkstra(t, );
for(int i = ; i <= m; ++i)
{
if(dis[][a[i].x] + dis[][a[i].y] + a[i].c > dis[][t])
{
ll dx = dis[][a[i].x] + dis[][a[i].y] + a[i].c - dis[][t] + ;
if(a[i].c - dx > ) ans[i] = dx; //别忘了减完后边权还得是正的
}
else
{
if(num[][a[i].x] * num[][a[i].y] == num[][t]) ans[i] = -;
else if(a[i].c > ) ans[i] = ; //减1后边权要大于0
}
}
for(int i = ; i <= m; ++i)
{
if(ans[i] == -) printf("YES\n");
else if(!ans[i]) printf("NO\n");
else printf("CAN %lld\n", ans[i]);
}
return ;
}

T3 归程的谜题

【题目描述】
NOIP 结束了,你踏上了归程。在大巴车上,你很无聊,于是你想了一个谜题来娱
乐一下。
若一个二维数组每个元素都是(或) 中的一个,那么这个数组被成为括号二维
数组。从二维数组的左上角(1; 1) 出发,每次向右或向下移动一格,直到走到右下角
(n;m),这样的路径被成为单调路径。自然地,一条单调路径上的所有字符按顺序相连
可以构成一个括号串。
如果一个括号二位数组的每一条单调路径所对应的括号串都是匹配的括号串,那
么这个括号二维数组被称为匹配的括号二维数组。
现在定义两个相同大小的匹配的括号二维数组的一个比较函数(比较数组a 和b)。
假设二维数组中每个元素都有一个优先级。优先级为1 到nm 的整数,且两两不同(设
优先级储存在一个和a; b 同样大小的二维数组c 中)。然后找到所有ai; j , bi; j 的位置。
如果有多个这样的位置,就选择ci; j 最小的位置。如果ai; j =(,则a < b,否则a > b;
若没有这样的位置,则a = b。
有了比较函数,我们可以给一定大小所有匹配的括号二维数组从小到大排序,你希
望找出具有指定大小的第k 个匹配的括号二维数组。
数据保证第k 个匹配的括号二维数组存在。
【输入格式】
从文件puzzle.in 中读入数据。
第一行有三个正整数n;m; k (1 n;m 500; 1 k 1018),分别表示二维数组的行
数、列数、你希望找到的匹配的括号二维数组的序数。
接下来n 行,每行m 个正整数,表示优先级数组(优先级两两不同)。
【输出格式】
输出到文件puzzle.out 中。
输出n 行,每行一个长度为m 的字符串,表示所求得的二维数组。
【样例1 输入】
3 2 2
3 6
1 4
2 5
第6 页共7 页
全国青少年信息学奥林匹克联赛NOIP 第二试归程的谜题(puzzle)
【样例1 输出】
()
)(
()
【样例2】
见选手目录下的puzzle/puzzle2.in 与puzzle/puzzle2.ans。
【子任务】
对于20% 的数据,n;m 10;
对于另20% 的数据,k 10;
对于另20% 的数据,n = 1。

就是CF123C。

题面我刚开始是没懂,考试剩后一个小时的时候我又读了一遍,总算明白了。还是那句话,多读几遍救懂了……

首先得发现这么个性质,看看下面这个图

这两条路线除了经过1和2号格子不同外,其他格子都相同,而又因为这两条路线都是合法的括号序列,所以可以推出,格子1和2的括号是相同的。那么进一步得出结论,每一个对角线上的括号都是相同的,换句话说只要确定了其中一条路径,那么整张图就确定了。

现在问题转化成了求一条第k小的长度为(n +m - 1)的合法括号序列。

首先我们将所有优先级映射到任意一条序列上,并保证序列第 i 位置的优先级是该格子所在对角线上最小的。接着顺着优先级尝试填这个格子括号,然后计算出在一些位置已经确定的括号

【2018暑假集训模拟一】Day2题解的更多相关文章

  1. 【2018暑假集训模拟一】Day1题解

    T1准确率 [题目描述] 你是一个骁勇善战.日刷百题的OIer. 今天你已经在你OJ 上提交了y 次,其中x次是正确的,这时,你的准确率是x/y.然而,你最喜欢一个在[0; 1] 中的有理数p/q(是 ...

  2. 2018.7.16 题解 2018暑假集训之Roads-roads

    题面描述 有标号为1--n的城市与单行道相连.对于每条道路有两个与之相关的参数:道路的长度以及需要支付的费用(用硬币的数量表示) 鲍勃和爱丽丝曾经生活在城市1.在注意到爱丽丝在他们喜欢玩的卡牌游戏中作 ...

  3. 2018.8.17 2018暑假集训 关于dp的一些感想(以目前的知识水平)

    学了这么长时间的dp似乎还是不怎么样 谨以此篇文字记录一年以来与dp斗智斗勇的各种经历 关于dp(也就是动态规划)似乎对于每个OIer来说都是一个永远的噩梦. 刚刚开始学dp的时候完全搞不明白(只是觉 ...

  4. 2018.8.19 2018暑假集训之maxnum

    昨天去做志愿服务去了没写成Q_Q 今天再来一道 先放题面描述 设有n个正整数(n<=20),将它们联成一排,组成一个最大的多位数 设有n个正整数(n<=20),将它们联成一排,组成一个最大 ...

  5. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  6. 暑假集训Day2 互不侵犯(状压dp)

    这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...

  7. 2015UESTC 暑假集训总结

    day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #49 - Streaming #4 (NOIP模拟赛Day2)

    A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...

随机推荐

  1. ADO.NET获取数据(DataSet)同时获取表的架构

    普通的ADO.NET获取DataSet的写法如下: using System.Configuration; using System.Data; using System.Data.SqlClient ...

  2. [javaSE] 看知乎学习反射

    简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息. 知乎:学习java应该如何理解反射?   余晖: 反射提供了一种运 ...

  3. CentOS 6 安装配置JDK+tomcat环境

    1.安装OpenJDK 这里安装的OpenJDK,是开源版本的JDK,我们平时自己电脑上安装的是 Sun JDK(也叫Oracle JDK),OpenJDK可以看作Sun JDK的精简版. 如果想安装 ...

  4. Redis——基础数据结构

    Redis提供了5种基础数据结构,分别是String,list,set,hash和zset. 1.String Redis所有的键都是String.Redis的String是动态字符串,内部结构类似J ...

  5. SQL Server系列文章目录

    SQL Server系列文章目录SQL Server系列文章目录SQL Server系列文章目录SQL Server系列文章目录

  6. Linux安装mysql教程

    安装之前需要先卸载mysql 1.1.下载压缩包 [root@guohaien package]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7 ...

  7. JSP (tomcat 内置对象)

    1.内置对象:    request: 方法:getParameter("txtName"):获取和页面上的name属性对象的value值       返回String       ...

  8. SSM(Spring MVC +Spring+Mybatis)整合——maven工程

    所谓的SSM 其实就是Spring MVC下整合mybatis. 具体的定义网络上都有,很详细. 这里只说项目的搭建步骤. 第一步 新建maven工程 工程目录如下: 配置pom.xml文件,引入所需 ...

  9. AsyncTask 处理耗时操作&&显示进度条

    在Android中实现异步任务机制有两种,Handler和AsyncTask.优缺点自己百度,推荐使用AsyncTask. private ProgressDialog dialog; //新建一个对 ...

  10. window下安装RabbitMQ

    RabbitMQ: MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消 ...