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连试试水的深浅..... ...
随机推荐
- Windows 下如何查看文件夹被哪个进程所占用
- Ansible架构
- Reset the default deployment target in Windows Phone Developer Tools
楼主在更新Windows Phone 8.1 SDK之后遇到一个很烦人的问题,编译选择调试目标列表没有数据.正常情况下都会有一个模拟器列表和真机的选项.肯定又是Preview的bug,问题产生的原因暂 ...
- Springboot +redis+⾕歌开源Kaptcha实现图片验证码功能
Springboot +redis+⾕歌开源Kaptcha实现图片验证码功能 背景 注册-登录-修改密码⼀般需要发送验证码,但是容易被 攻击恶意调⽤ 什么是短信-邮箱轰炸机 手机短信轰炸机是批.循环给 ...
- 火爆的文字游戏你玩了吗?「GitHub 热点速览 v.22.06」
不知道你有没有被 Wordle 这款游戏刷屏,在本期热点速览的特推部分选了一个 React 编写的开源版本同你分享,而本次公众号摘要也是一个提示, 只不过这个只能盲猜了.别小瞧 Wordle 这个游戏 ...
- Ubuntu 18.04 修改默认源为国内源
1.备份/etc/apt/sources.list #备份 cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.在/etc/apt/sources ...
- aidl的应用场景
支付宝 package com.tesy.alipay; import com.test.alipay.Iservice.Stub; import android.app.Service; impor ...
- 一键部署mysql 无修改直接cp 执行 100% 有效
一键部署mysql 无修改直接cp 执行 100% 有效 将安装包拖至/opt目录下,编一个脚本文件,然后source执行脚本,等脚本执行完成, 即可使用mysql -u root -p点击 ...
- AppiumForWin安装
尝试安装Windows版本的Appium 参考:http://www.cnblogs.com/fnng/p/4540731.html 第一步:安装node https://nodejs.org/en/ ...
- DelayQueue延迟队列-实现缓存
延迟阻塞队列DelayQueue DelayQueue 是一个支持延时获取元素的阻塞队列, 内部采用优先队列 PriorityQueue 存储元素, 同时元素必须实现 Delayed 接口:在创建元素 ...