Codeforces Round #773 (Div. 2)D,E
D. Repetitions Decoding
传送门
题目大意:
一个长为
n
(
n
2
≤
250000
)
n(n^2\leq250000)
n(n2≤250000)的序列,每个元素
a
i
(
1
≤
a
i
≤
1
0
9
)
a_{i}(1\leq a_{i}\leq 10^9)
ai(1≤ai≤109)
可以执行若干次操作,每次在序列中的某个位置插入两个相同的数字,给出一组操作序列,使得操作后的序列可以划分为若干个长为偶数的段,每段长度为
k
i
k_{i}
ki,在该段内满足
a
j
=
a
j
+
k
i
2
a_{j}=a_{j+\frac {k_{i}}{2}}
aj=aj+2ki,并给出最终各个段的长度,如果操作序列不存在,输出
−
1
-1
−1。
思路:
考虑到在执行操作的过程当中,每种数字个数的奇偶性不会发生变化,而最终的序列如果要满足要求,那么每种数字的个数必须都是偶数,于是当一开始存在某种数字的个数是奇数时,就不存在操作序列。
之后我们可以用以下的方法来进行构造,不断从前往后找一对相同的数字,假设找到的为
1
1
1,并且该序列为
1
1
1
2
2
2
3
3
3
1
1
1
.
.
.
...
... 那么我们可以在一对相同的数中的后一个的后面不断对称地插入位于这一对数之间的数字,之后序列变为
1
1
1
2
2
2
3
3
3
1
1
1
2
2
2
3
3
3
3
3
3
2
2
2
.
.
.
...
...,于是可以发现,
1
1
1
2
2
2
3
3
3
1
1
1
2
2
2
3
3
3就构成了一个合法的段,将它们拿掉后,序列变为
3
3
3
2
2
2
.
.
.
...
...,也就相当于删除了我们之前找到的一对数字,并将他们之间的数字翻转,于是重复这个步骤,就可以给出合法的操作序列了。显然这个步骤最多执行
n
2
\frac{n}{2}
2n次,每次执行需要
O
(
n
)
O(n)
O(n)的时间,所以可以在
O
(
n
2
)
O(n^2)
O(n2)内完成。
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
#define all(x) x.begin(),x.end()
//#define int LL
#define lc p*2+1
#define rc p*2+2
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#pragma warning(disable :4996)
const double eps = 1e-8;
const LL mod = 1000000007;
const LL MOD = 998244353;
const int maxn = 200010;
int T, N;
vector<int>A;
map<int, int>mp;
void solve()
{
for (auto& c : mp)
{
if (c.second % 2)
{
cout << -1 << endl;
return;
}
}
vector<PII>op;
vector<int>len;
int base = 0;
while(!A.empty())
{
auto beg = A.begin();
auto it2 = beg + 1;
while (*it2 != *beg)
it2++;
int num = it2 - beg;
if (it2 == beg + 1)
len.push_back(2);
else
{
len.push_back(num * 2);
auto tmp = beg + 1;
int pos = base + num + 1;
while (tmp != it2)
{
op.push_back(PII(pos++, *tmp));
tmp++;
}
reverse(A.begin(), it2);
}
A.erase(A.begin() + num - 1);
A.erase(A.begin() + num - 1);
base += num * 2;
}
cout << op.size() << endl;
for (auto& c : op)
cout << c.first << ' ' << c.second << endl;
cout << len.size() << endl;
for (auto& c : len)
cout << c << ' ';
cout << endl;
}
int main()
{
IOS;
cin >> T;
while (T--)
{
cin >> N;
A.clear(), mp.clear();
int num;
for (int i = 1; i <= N; i++)
{
cin >> num;
A.push_back(num);
mp[num]++;
}
solve();
}
return 0;
}
E. Anonymity Is Important
传送门
题目大意:
n
(
1
≤
n
≤
2
×
1
0
5
)
n(1\leq n\leq2\times10^5)
n(1≤n≤2×105)个人,编号
1
∼
n
1\sim n
1∼n,
q
(
1
≤
q
≤
2
×
1
0
5
)
q(1\leq q\leq2\times10^5)
q(1≤q≤2×105)次询问:
0
0
0
l
l
l
r
r
r
x
x
x:当
x
=
0
x=0
x=0时,表示
[
l
,
r
]
[l,r]
[l,r]内没有人生病;
x
=
1
x=1
x=1时,
[
l
,
r
]
[l,r]
[l,r]内至少
1
1
1个人生病。
1
1
1
j
j
j:回答第
j
j
j个人是否生病,无法确定则输出N/A
思路:
x
=
0
x=0
x=0 的情况我们很容易处理,用set
来维护所有尚未确定不会生病的人,对于每条
0
0
0
l
l
l
r
r
r
0
0
0 的信息,可以将
[
l
,
r
]
[l,r]
[l,r] 内所有人从set
中删去。
当查询到
j
j
j 时,如果
j
j
j 不在set
内,那么就可以确定
j
j
j 没有生病。否则
j
j
j 要么生病,要么状态无法确定。如果要确定
j
j
j 是生病的,必须在查询之前出现过一条形如
0
0
0
l
l
l
r
r
r
1
1
1 的信息,使得当前在
[
l
,
r
]
[l,r]
[l,r] 内,有且仅有
j
j
j 一个人仍在set
当中(如果多于一个说明每个人都有可能是病人,就无法判断了)。于是我们在set
中找到
j
j
j 的前驱
l
l
l 以及后继
r
r
r (可以在set
中额外加入
0
0
0 和
n
+
1
n+1
n+1 两个人便于实现),我们可以枚举所有位于
[
l
+
1
,
j
]
[l+1,j]
[l+1,j] 内的查询信息的左端点,来看是否有一个对应的右端点的值
<
r
<r
<r 即可(因为所有信息都合法,所以左右右端点的值都会
>
=
j
>=j
>=j ),这可以用线段树来高效解决。
用一个线段树来维护每个左端点区间对应的右端点的最小值,对于每条
0
0
0
l
l
l
r
r
r
1
1
1 的信息。我们将左端点
l
l
l处的值单点修改为
m
i
n
(
d
a
t
[
l
]
,
r
)
min(dat[l],r)
min(dat[l],r) 即可。在查询时只需要查询区间
[
l
+
1
,
j
]
[l+1,j]
[l+1,j] 即可,复杂度
O
(
(
n
+
q
)
l
o
g
n
)
O((n+q)logn)
O((n+q)logn)。
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
#define all(x) x.begin(),x.end()
//#define int LL
#define lc p*2+1
#define rc p*2+2
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#pragma warning(disable :4996)
const double eps = 1e-8;
const LL mod = 1000000007;
const LL MOD = 998244353;
const int maxn = 200010;
int N, Q;
set<int>S;
struct {
int l, r, dat;
}tr[maxn * 4];
void build(int p, int l, int r)
{
tr[p].l = l, tr[p].r = r;
if (l + 1 == r)
{
tr[p].dat = inf;
return;
}
int mid = (l + r) / 2;
build(lc, l, mid), build(rc, mid, r);
tr[p].dat = min(tr[lc].dat, tr[rc].dat);
}
void modify(int p, int a, int x)
{
if (tr[p].l + 1 == tr[p].r)
{
tr[p].dat = min(tr[p].dat, x);
return;
}
int mid = (tr[p].l + tr[p].r) / 2;
if (a < mid)
modify(lc, a, x);
else
modify(rc, a, x);
tr[p].dat = min(tr[lc].dat, tr[rc].dat);
}
int query(int p, int l, int r)
{
if (tr[p].l >= l && tr[p].r <= r)
return tr[p].dat;
int mid = (tr[p].l + tr[p].r) / 2;
if (r <= mid)
return query(lc, l, r);
if (l >= mid)
return query(rc, l, r);
return min(query(lc, l, mid), query(rc, mid, r));
}
void solve()
{
build(0, 1, N + 1);
for (int i = 0; i <= N + 1; i++)
S.insert(i);
int type, l, r, x, j;
while (Q--)
{
cin >> type;
if (type == 0)
{
cin >> l >> r >> x;
if (x == 0)
{
while (!S.empty())
{
int pos = *S.lower_bound(l);
if (pos <= r)
S.erase(pos);
else
break;
}
}
else
modify(0, l, r);
}
else
{
cin >> j;
if (!S.count(j))
cout << "NO" << endl;
else
{
auto itl = S.lower_bound(j), itr = S.upper_bound(j);
itl--;
int l = *itl, r = *itr;
if (query(0, l + 1, j + 1) < r)
cout << "YES" << endl;
else
cout << "N/A" << endl;
}
}
}
}
int main()
{
IOS;
cin >> N >> Q;
solve();
return 0;
}
Codeforces Round #773 (Div. 2)D,E的更多相关文章
- Codeforces Round #415 (Div. 2)(A,暴力,B,贪心,排序)
A. Straight «A» time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- Codeforces Round #427 (Div. 2)—A,B,C,D题
A. Key races 题目链接:http://codeforces.com/contest/835/problem/A 题目意思:两个比赛打字,每个人有两个参数v和t,v秒表示他打每个字需要多久时 ...
- Codeforces Round #239 (Div. 1)C, 407C
题目链接:http://codeforces.com/contest/407/problem/C 题目大意:给一个长度为n的数列,m次操作,每次操作由(li, ri, ki)描述,表示在数列li到ri ...
- Codeforces Round #372 (Div. 2) A ,B ,C 水,水,公式
A. Crazy Computer time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- Codeforces Round #371 (Div. 2) A ,B , C 水,水,trie树
A. Meeting of Old Friends time limit per test 1 second memory limit per test 256 megabytes input sta ...
- Codeforces Round #725 (Div. 3) A-D,F题解
A. Stone Game 思路:总共3种情况,都从最左端被拿走,都从最右端被拿走,左侧的从最左端被拿走且右侧的从最右端被拿走,取最小值即可 代码: //CF-725.A #include<bi ...
- Codeforces Round #773 (Div. 2)
这一场打的非常一般,不过把D想出来了(当然只剩10min没有写出来). A.Hard Way 题意:(很怪的题,我读题读半天)给你一个三角形(端点都在整数点上),问从x轴往上划线(不一定垂直)画不到的 ...
- Codeforces Round #525 (Div. 2)
Codeforces Round #525 (Div. 2) 哎,忍不住想吐槽一下,又要准备训练,又要做些无聊的事,弄得我都想退出了. 好好的训练不好么???? 只能做出两道水题,其实C题,感觉做出来 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
随机推荐
- 微服务架构 | 5.4 Sentinel 流控、统计和熔断的源码分析
目录 前言 1. Sentinel 的自动装配 1.2 依赖引入 1.3 SentinelWebAutoConfiguration 配置类 1.4 CommonFilter 过滤器 1.5 小结 2. ...
- 计算机网络再次整理————UDP例子[六]
前言 简单的说,UDP 没有 TCP 用的广泛,但是还有很多是基于UDP的程序的,故而简单介绍一下. 正文 秉承节约脑容量的问题,只做简单的介绍和例子,因为自己几乎也没怎么用过UDP. 只是了解和知晓 ...
- 计算机开放电子书 2021 RC2
下载方式 pip install CDNDrive # 或 # pip install git+https://github.com/apachecn/CDNDrive cdrive download ...
- Mysql自序整理集
1.事务 mysql事务是用于处理操作量大.复杂性高的数据 1. 事务特性 原子性:保证每个事务所有操作要么全部完成或全部不完成,不可能停滞在中间环节:如事务在执行过程中出现错误,则会回滚到事务开始之 ...
- 深入聊一下const关键字
const是一个C语言的关键字,它限定一个变量不允许被改变.使用const在一定程序上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解别人的程序有所帮助. 1.c ...
- hihoCoder挑战赛1 毁灭者问题
题目链接:http://hihocoder.com/problemset/problem/1034 数据结构题,由于每个魔法单位有着不同的回复速度和上限,所以不能根据吸收时间点进行查询和更新.但是如果 ...
- 优化UITableViewCell高度计算的那些事 by --胡 xu
这篇总结你可以读到: UITableView高度计算和估算的机制 不同iOS系统在高度计算上的差异 iOS8 self-sizing cell UITableView+FDTemplateLayout ...
- 实现“手机qq”侧滑菜单 -- 吴欧
基本数据采集 经过体验,手机QQ采用的应该是线性动画,即视图缩放比例等随手指在屏幕上滑动的距离以一次方程的形式变化. 提取基本数据,向右侧滑达到最大幅度时: 1. 右侧主视图左边界距离屏幕左边界的 ...
- MySQL日志管理、备份与恢复
MySQL日志管理.备份与恢复 目录 MySQL日志管理.备份与恢复 一.MySQL日志管理 1. MySQL日志路径 2. 设置.修改日志路径 3. 查询日志功能是否开启 二.MySQL备份与恢复 ...
- Oracle 撤回已经提交的事务
在PL/SQL操作了一条delete语句习惯性的commit 了,因少加了where条件 导致多删了数据 1.查询视图v$sqlarea,找到操作那条SQL的时间(FIRST_LOAD_TIME) s ...