传送门


题意:有一个长为\(n\)的排列\(p\),设\(S_i=\sum_{j=1}^{i-1}p_j\cdot[p_j<p_i]\),给出\(S\),要求还原出\(p\)。保证有解,\(n\leq 2\times 10^5\)。

考虑倒序将\(S\)还原为全\(0\)的序列,从小到大依次考虑插入每个数的影响。假设在位置\(x\)插入\(i\),显然此时\(S_x=0\),且会使得位置\(x\)右侧的每一个未插入数字的\(S_y\)都减去\(i\)。因此对于第\(i\)个数,唯一合法的位置就是所有\(S_x=0\)的位置中最右侧的那个。由于保证有解,维护最小值,在线段树上二分即可。

Code:

#include <cstdio>
#include <cctype>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
#define R register
#define ll long long
using namespace std;
const int N = 210000, K = N << 2;
const ll inf = 1e18; int n, lt[K], rt[K], p[N];
ll a[N], minVal[K], tag[K];
inline void pushdown(int); template <class T> inline void read(T &x) {
x = 0;
char ch = getchar(), w = 0;
while (!isdigit(ch))
w = (ch == '-'), ch = getchar();
while (isdigit(ch))
x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
x = w ? -x : x;
return;
} void build(int k) {
if (lt[k] == rt[k]) {
minVal[k] = a[lt[k]];
return;
}
int mid = (lt[k] + rt[k]) >> 1, l = k << 1, r = (k << 1) + 1;
lt[l] = lt[k], rt[l] = mid, lt[r] = mid + 1, rt[r] = rt[k];
build(l), build(r), minVal[k] = min(minVal[l], minVal[r]);
return;
} void modify(int k, int x, int y, ll w) {
if (lt[k] >= x && rt[k] <= y) {
minVal[k] += w, tag[k] += w;
return;
}
pushdown(k);
int mid = (lt[k] + rt[k]) >> 1, l = k << 1, r = (k << 1) + 1;
if (x <= mid) modify(l, x, y, w);
if (y > mid) modify(r, x, y, w);
minVal[k] = min(minVal[l], minVal[r]);
return;
} int query(int k) {
if (lt[k] == rt[k]) {
minVal[k] = inf;
return lt[k];
}
int l = k << 1, r = (k << 1) + 1, ret;
pushdown(k), ret = query(minVal[r] ? l : r);
minVal[k] = min(minVal[l], minVal[r]);
return ret;
} inline void pushdown(int k) {
int l = k << 1, r = (k << 1) + 1;
if (tag[k]) {
modify(l, lt[k], rt[k], tag[k]);
modify(r, lt[k], rt[k], tag[k]);
tag[k] = 0;
}
return;
} int main() {
read(n);
for (R int i = 1; i <= n; ++i)
read(a[i]);
lt[1] = 1, rt[1] = n, build(1);
for (R int i = 1; i <= n; ++i) {
int pos = query(1);
p[pos] = i, modify(1, pos, n, -i);
}
for (R int i = 1; i <= n; ++i)
printf("%d ", p[i]);
return 0;
}

[CF1208D] Restore Permutation的更多相关文章

  1. D. Restore Permutation(权值线段树)

    D. Restore Permutation time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  2. D. Restore Permutation

    D. Restore Permutation 就是给一个n个数的全排,然后bi记录比ai小且在排在ai前面的数的和,求ai 树状数组维护,二分 #include<bits/stdc++.h> ...

  3. [Codeforces 1208D]Restore Permutation (树状数组)

    [Codeforces 1208D]Restore Permutation (树状数组) 题面 有一个长度为n的排列a.对于每个元素i,\(s_i\)表示\(\sum_{j=1,a_j<a_i} ...

  4. D. Restore Permutation 树状数组+二分

    D. Restore Permutation 题意:给定n个数a[i],a[ i ]表示在[b[1],b[i-1]]这些数中比 b[i]小的数的和,要你构造这样的b[i]序列 题解:利用树状数组 求比 ...

  5. 线段树维护最后一个0的位置(Restore Permutation)Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)

    题意:https://codeforc.es/contest/1208/problem/D 给你长度为n的序列,s[i]的值为p[1]到p[i-1]中比p[i]小的数的和,让你求出p序列. 思路: 首 ...

  6. 1208D Restore Permutation

    题目大意 给你一个序列s 让你求一个1~n的序列 使得对于第i个位置它前面所有小于p[i]的数的和恰好为s[i] 分析 我们可以从后往前确定每一位 每次一二分找到恰好等于s[i]的数 但是我们发现这样 ...

  7. cf1208 D Restore Permutation (二分+树状数组)

    题意 让你构造一个长度为n的序列,记为p1……pn,(这个序列是1~n的全排列的一种) 给你n个数,记为s1……sn,si的值为p1……pi-1中小于pi的数的和. 思路 显然,应该倒着来,也就是从p ...

  8. 一句话CF

    目录 \(\bf {Round \ \#500 \ (Div. \ 1)}\) \(\bf {Round \ \#589 \ (Div. \ 2)}\) \(\bf {Avito \ Cool \ C ...

  9. Manthan Codefest 19 题解

    这套题还是有点质量的吧 -- 题目链接 A. XORinacci 傻叉签到题,因为异或的性质所以这个序列的循环节长度只有 \(3\) -- 查看代码 B. Uniqueness 因为序列长度乃至数的种 ...

随机推荐

  1. python - del 方法

    转自:http://blog.csdn.net/love1code/article/details/47276683 python中的del用法比较特殊,新手学习往往产生误解,弄清del的用法,可以帮 ...

  2. Jmeter之HTTP常用配置元件(默认、头信息和cookies)

    在进行HTTP接口的测试时,会用到部分常用的配置元件,现在简单的说明: 一.HTTP请求默认值 在测试同一个项目的HTTP请求接口时,会存在部分相同的信息,可以将这些相同的信息提取出来,使用HTTP请 ...

  3. C#与Java覆盖问题

    C#继承类中如含有相同的方法,避免冲突使用new关键字.在不同对象中分别对应该方法.若使用override关键字则,基类中的方法被覆盖. 如需调用非覆盖的则使用base关键字. Java中的继承类方法 ...

  4. 使用事件CreateEvent注意事项 多进程同步的方法

    https://www.cnblogs.com/aakuang/p/3514658.html 使用事件CreateEvent注意事项   HANDLECreateEvent( LPSECURITY_A ...

  5. Java课堂疑问解答与思考4

    一. 请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 答:定义的三个字符串如果相等,系统自动创建一个,并调用这个,对于由new创建的字符 ...

  6. vim加脚本注释和文本加密

    vim /etc/vimrc 一.李导版本 autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" fun ...

  7. wiki团队协作软件Confluence

    一.准备环境 准备环境 lamp(Linux.apache.mysql.php)框架 centos7 java jdk1.8.0_111 Distrib 5.5.52-MariaDB confluen ...

  8. Canvas入门06-线段与像素边界

    我们知道,使用以下2个API可以绘制一条线段: moveTo(x, y) 向当前路径中增加一条子路径,该子路径只包含一个点,此为线段的起始点 lineTo(x, y) 将线段的下一个点加入子路径中 c ...

  9. 第九周课程总结&实验报告7

    实验任务详情: 完成火车站售票程序的模拟.要求:(1)总票数1000张:(2)10个窗口同时开始卖票:(3)卖票过程延时1秒钟:(4)不能出现一票多卖或卖出负数号票的情况. 实验代码: package ...

  10. 为什么 Java 线程没有 Running 状态?

    Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...