这是一场比较难的div2 ... 比赛的时候只出了AB

A很有意思 给出n个数 要求随意的把相邻的数合并成任意多数 最后没有为0的数 输出合并区间个数与区间

可以想到0可以合到任何数上并不改变该数的性质 所以如果不全是0 最后一定是有答案的 把所有的0都合并到最近的非0数上去 非0数不变

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
int n ;
int a[105];
int l[105];
int r[105];
int main(){
scanf("%d",&n);
for(int i = 1 ;i<=n;i++)scanf("%d",&a[i]);
bool ok = true;
int res = 0;
int cnt = 0;
for(int i = 1; i<=n;i++){
if(a[i]!= 0){
cnt ++ ;
l[cnt] = i;
r[cnt] = i;
}
}
if(cnt == 0){
printf("NO\n");
return 0 ;
}
r[0] = 0 ;
l[cnt+1] = n + 1;
for(int i = 1; i<= cnt ;i ++){
l[i] = r[i-1] + 1;
r[i] = l[i+1] - 1;
}
printf("YES\n");
printf("%d\n",cnt);
for(int i = 1 ; i<=cnt ; i ++){
printf("%d %d\n",l[i],r[i]);
}
}

B很无聊..下三子棋 现在该我们下x了 能否一步胜利或者不走就胜利了呢?

写一个很手动的check函数 先判断能否直接胜利 再枚举每一个可以放的位置 放下再check

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
char s[50][50];
bool check(char a){
for(int i = 1 ; i<=4 ; i ++){
for(int j = 1 ; j<= 2 ; j ++ ){
if(s[i][j] == s[i][j+1] &&s[i][j+1] == s[i][j+2] && s[i][j+1] == a){
return true;
}
}
}
for(int j = 1 ; j<=4 ; j ++){
for(int i = 1 ; i<= 2 ; i ++ ){
if(s[i][j] == s[i+1][j] &&s[i+1][j] == s[i+2][j] && s[i][j] == a){
return true;
}
}
}
for(int i = 1; i<=2 ;i ++){
if(s[i][i] == s[i+1][i+1] &&s[i+1][i+1] == s[i+2][i+2] && s[i][i] == a)return true ;
}
if(s[2][1] == s[3][2] && s[3][2] == s[4][3] &&s[4][3] == a)return true;
if(s[1][2] == s[2][3] && s[2][3] == s[3][4] &&s[3][4] == a)return true; if(s[2][4] == s[3][3] && s[3][3] == s[4][2] &&s[4][2] == a)return true;
if(s[1][3] == s[2][2] && s[2][2] == s[3][1] &&s[3][1] == a)return true; if(s[1][4] == s[2][3] && s[2][3] == s[3][2] && s[3][2] == a)return true;
if(s[2][3] == s[3][2] && s[3][2] == s[4][1] && s[4][1] == a)return true;
return false ;
}
int main(){
for(int i = 1;i<=4 ; i++)scanf("%s",s[i] + 1);
if(check('x')){
printf("YES\n");
return 0;
}
if(check('o')){
printf("NO\n");
return 0 ;
}
for(int i = 1 ; i <= 4;i++){
for(int j = 1 ; j<=4 ;j ++){
if(s[i][j] == '.'){
s[i][j] = 'x';
if(check('x')){
printf("YES\n");
return 0 ;
}
s[i][j] = '.';
}
}
}
printf("NO\n");
}

C一个比较耗费时间的字符串模拟 给出一些人的名字和他们说的话 有些话的发言人用?代替 要求 相邻的两句话不会是同一个人说的 一个人说的话不会提到自己的名字

先做一个字符串模拟 用map把人名编号 再用r[]记录每句话的发言人 用cx[][]来记录每句话中出现的人名 用ans[]来处理最后的答案

最后我们 会得到一个cx数组 记录每句没有主人的话能选择的人

会发现贪心好像是不可做的 当前这句话 如果我们做出一些选择 可能会影响到下一个人的选择

搜索的话 如果100句话都是?也会超时

可以利用cx[][]数组和r[]数组 做一个dp题

如果想不到怎么dp 可以去代码中寻找注释~

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
string name[1050];
map<string , int >p;
int n , m ;
char s[1050];
string ans[1050];
int r[1050];
bool cx[105][105]; int cnt ;
int us[105]; int main(){
int t;
scanf("%d",&t);
while(t -- ){
memset(r , -1 ,sizeof(r));
scanf("%d",&n);
p.clear();
string tm = "";
for(int i = 1; i<=n ;i ++){
scanf("%s",s);
int len = strlen(s);
tm = "" ;
for(int j = 0 ; j<len ;j ++)tm += s[j];
p[tm] = i ;
name[i] = tm ;
}
scanf("%d",&m);
getchar();
bool ok = true;
memset(cx , false,sizeof(cx));
for(int i = 1; i<=m;i ++){
gets(s);
int len = strlen(s);
ans[i] = "";
if(s[0] == '?'){
r[i] = -1;
for(int j = 2 ; j<len ; j ++){
tm = "";
while(j < len && s[j] != '.' && s[j] != ',' && s[j] != '!' && s[j] != '?' && s[j] != ' '){
tm += s[j] ;
j ++ ;
}
if(tm != ""){
int z = p[tm];
if(z != 0){
cx[i][z] = true ;
}
}
}
for(int j = 1 ; j < len ; j ++)ans[i] += s[j] ;
}
else {
tm = "" ;
int j ;
for(j = 0; s[j] !=':' ; j ++ ){
tm += s[j];
}
r[i] = p[tm];
j ++ ;
for(int k = 0 ; k < len ;k ++)ans[i] += s[k] ;
for(; j<len ; j ++){
tm = "";
while(j < len && s[j] != '.' && s[j] != ',' && s[j] != '!' && s[j] != '?' && s[j] != ' '){
tm += s[j] ;
j ++ ;
}
if(tm != ""){
int z = p[tm];
if(z != 0){
cx[i][z] = true ;
}
}
}
}
}
if(ok == false) {
printf("Impossible\n");
continue ;
}
r[0] = r[m+1] = -1 ;
/**
r[i] 第几句话发言人的编号 -1代表?
name[] 1-n号人的名字
cx[u][v] 第u句话中提到了v */
bool dp[105][105] ;
int pre[105][105] ;
/**
dp[i-1][!j] == true -> dp[i][j] = true
pre[i][j] = pre[i-1][!j]
*/
memset(dp , false , sizeof(dp)) ;
for(int i = 1 ; i <= n ; i ++ )dp[0][i] = true ;
for(int i = 1 ; i <= m ; i ++ ){
if(r[i] != -1) {
if(i == 1) {
dp[i][r[i]] = true ;
continue ;
}
for(int j = 1; j <= n ; j ++ ){
if(j != r[i] && dp[i-1][j] == true) {
dp[i][r[i]] = true ;
pre[i][r[i]] = j ;
}
}
continue ;
}
for(int j = 1; j <=n ; j ++ ){
if(cx[i][j] == true) continue ;
if(j == r[i+1]) continue ;
if(j == r[i-1]) continue ;
for(int k = 1; k <= n ; k ++ ){
if(j == k && i != 1)continue ;
if(dp[i-1][k] == true){
dp[i][j] = true ;
pre[i][j] = k ;
}
}
}
}
/// 利用pre数组反转录入答案
cnt = m ;
bool fin = false ;
for(int i = 1; i <= n ;i ++ ){
if(dp[m][i] == true){
us[cnt] = i ;
int w = i;
while(cnt >= 2) {
int k = pre[cnt][w] ;
cnt -- ;
us[cnt] = k ;
w = k ;
}
fin = true ;
break ;
}
}
if(fin == false){
printf("Impossible\n");
continue ;
}
///ans
for(int i = 1; i <= m ; i ++ ){
if(r[i] != -1){
cout << ans[i] << endl ;
}
else {
cout << name[us[i]] << ans[i] << endl ;
}
}
}
}

D给出n个区间 要求必须选择k个区间 使这k个区间的交集最大

k个区间的交集形成的区间 它的l是这几个区间中的最大的l 而r是这几个区间中的最小的r

应当选择k个区间 使它们有最小的l和最大的r 所以动态的去想 我们可以将l从小往大选 并选择最大化的r 维护一个ans

先进行排序 使l尽可能的小 在其基础上r尽可能的小 这样 我们从1-n枚举区间 就可以直接得到最大的l了

因为我们选择的l 是逐渐增大的 所以为了保存足够大的r 需要一个优先队列来做 维护一个 < 的优先队列 存放每个区间的r

1-n枚举区间的过程 每次我们选择一个区间 向优先队列中压入它的r 如果当前队列的size < k 说明未达到题目要求 暂且不管

如果size > k  我们就q.pop 弹出当前最小的r 由于我们是动态维护了ans 所以 如果弹出最小的r 使我们失去了一个l

1 如果这个l 是当前区间最大的l 那么当前结果已经保留进了ans

2 如果这个l 不是当前区间最大的l 那么这个区间的移除会使ans增大

如果size == k 这个状态可能是size < k 或者 size > k 来的 如果是前者 我们就需要开始更新ans(事实上这一幕只会在第k个数字出现)

如果是后者 我们就需要分析 这个新区间 会不会已经被弹出去了?

1 弹出去了 那么现在其实没变化 不需要做什么改变

2 没弹出去 那么现在就需要更新一下答案 我们可以肯定 当前的交集区间的l 一定是新区间的l(sort的结果) 而r 就是优先队列的top 所以 res = q.top - 新区间.l + 1

判断是否弹出 需要判断新区间的r与top的关系

有一个问题是 新区间的r 可能已经被弹出去了 当前区间并没有加进去 但是因为优先队列有r=新区间.r 所以被误判

其实是不会造成影响的 因为对于这种情况 一定会有过去的res >= 现在的res

所以这样模拟完最后就可以得出ans了

题目要求输出一下区间的选择

如果ans是0 随便输出k个数就可以了

如果不是的话 由于我们不确定当前解是不是最优解 所以 过程中我们无法更新区间数的ans

但是我们可以在优先队列中 伴随r加上一个id 然后再跑一遍枚举 当res == ans的时候 队列里的id就是答案啦

聪明的你一定看到这里就完全理解了吧

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
int n , m ;
struct node {
int l , r ;
int id ;
bool operator < (const node &a )const{
return a.r < r ;
}
}a[300050];
bool cmp(node a, node b ){
if(a.l == b.l )return a.r < b.r ;
else {
return a.l < b.l ;
}
}
int c[300050] ;
int main(){
scanf("%d%d",&n, &m );
for(int i = 1; i <= n ;i ++ ){
scanf("%d%d",&a[i].l , & a[i].r ) ;
a[i].id = i ;
}
sort(a+1,a+1+n,cmp) ;
int ans = 0 ;
priority_queue<node>q;
int l = 0;
for(int i = 1; i <= n ; i ++ ){
node b = a[i] ;
q.push(b) ;
if(q.size() < m){
l = a[i].l ;
}
if(q.size() > m){
q.pop() ;
}
if(q.size() == m){
if(b.r >= q.top().r){
int res = q.top().r - b.l + 1 ;
if(res > ans)ans = res ;
l = b.l ;
}
}
}
printf("%d\n",ans) ;
if(ans == 0){
for(int i = 1; i <= m ; i ++ ){
printf("%d",i);
if(i == m)printf("\n");
else printf(" ");
}
}
else {
while(!q.empty())q.pop(); for(int i = 1; i <= n ; i ++ ){
node b = a[i] ;
q.push(b) ;
if(q.size() < m){
l = a[i].l ;
}
if(q.size() > m){
q.pop() ;
}
if(q.size() == m){
if(b.r >= q.top().r){
int res = q.top().r - b.l + 1 ;
if(res == ans){
int z = q.size();
while(!q.empty()){
c[z] = q.top().id ;
q.pop() ;
z-- ;
}
sort(c+1,c+1+m);
for(int j = 1; j <=m ;j ++ ){
printf("%d",c[j]);
if(j == m)printf("\n");
else printf(" ");
}
break ;
}
}
}
}
}
}

Codeforces Round #390 (Div. 2) A B C D的更多相关文章

  1. Codeforces Round #390 (Div. 2) D. Fedor and coupons(区间最大交集+优先队列)

    http://codeforces.com/contest/754/problem/D 题意: 给定几组区间,找k组区间,使得它们的公共交集最大. 思路: 在k组区间中,它们的公共交集=k组区间中右端 ...

  2. Codeforces Round #390 (Div. 2) C. Vladik and chat(dp)

    http://codeforces.com/contest/754/problem/C C. Vladik and chat time limit per test 2 seconds memory ...

  3. Codeforces Round #390 (Div. 2) A. Lesha and array splitting

    http://codeforces.com/contest/754/problem/A 题意: 给出一串序列,现在要把这串序列分成多个序列,使得每一个序列的sum都不为0. 思路: 先统计一下不为0的 ...

  4. Codeforces Round #390 (Div. 2)

    时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing ...

  5. Codeforces Round #390 (Div. 2) E(bitset优化)

    题意就是一个给出2个字符矩阵,然后进行匹配,输出每个位置的匹配的结果 (超出的部分循环处理) 一种做法是使用fft,比较难写,所以没有写 这里使用一个暴力的做法,考虑到一共只出现26个字符 所以使用一 ...

  6. Codeforces Round #390 (Div. 2) D

    All our characters have hobbies. The same is true for Fedor. He enjoys shopping in the neighboring s ...

  7. Codeforces Round #390 (Div. 2) B

    Ilya is an experienced player in tic-tac-toe on the 4 × 4 field. He always starts and plays with Xs. ...

  8. Codeforces Round #390 (Div. 2) A

    One spring day on his way to university Lesha found an array A. Lesha likes to split arrays into sev ...

  9. Codeforces Round #390 (Div. 2) A+B+D!

    A. Lesha and array splitting 水题模拟.(0:10) 题意:给你一个n个元素的数组,求能否把这个数组分成若干连续小段,使得每段的和不为0.如有多种解输出任意一个. 思路:搞 ...

随机推荐

  1. VMware下安装centos6.7的步骤

    一.虚拟机的创建 1.点击创建新的虚拟机(图片红框的位置) 2.选择自定义安装.下一步(根据自己的需要有选择的进行选择) 3.新装的虚拟机的版本和虚拟机兼容的产品以及这个版本的虚拟机的限制(这个窗口没 ...

  2. poj 3670(LIS)

    // File Name: 3670.cpp // Author: Missa_Chen // Created Time: 2013年07月08日 星期一 21时15分34秒 #include < ...

  3. 1624 取余最长路(set)

    1624 取余最长路 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱 ...

  4. 记录--Gson、json转实体类、类转json

    需要导入Gson jar包 最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson ...

  5. PHP 获得域控内用户的计算机登录名

    一个需求: 在域控范围获得访问用户的计算机名.方法: 1.测试软件环境: XAMPP Control Panel V3.2.1 ,  Apache version 2.4.7 2.Apache 2.2 ...

  6. Time-series Storage Layer Time Series Databases 时间序列

    w 关于时间序列数据库的思考-CSDN.NET  http://www.csdn.net/article/2015-07-13/2825192  存储和处理时间序列数据(“Time Series Da ...

  7. TreeMap详细介绍(源码解析)和使用示例

    本文转自 http://www.cnblogs.com/skywang12345/p/3310928.html 概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学 ...

  8. jquery拓展插件-popup弹窗

    css:<style> /* 公共弹出层 */ .popWrap{position: fixed;left: 0;top: 0; width: 100%;height: 100%;z-in ...

  9. 常用模块一(os模块、序列化模块(json和pickle))

    一.os模块 os模块是与操作系统交互的一个接口. import os # 和文件和文件夹的操作有关 os.makedirs('dirname1/dirname2') # 可生成多层递归目录 os.r ...

  10. https-SSL请求

    # coding:utf-8import requests# 禁用安全请求警告from requests.packages.urllib3.exceptions import InsecureRequ ...