Codeforece E. Anton and Permutation
主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h) a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans-1,ans+<r的,->r的 ans-<l的,+>l的,区间比k大的数量或者区间第k大等类似的可以用第二类主席树弄
#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <set>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mod 10007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-12;
const int N = 500005 + 5;
const int M = 200005;
int n, m, d;
int a[500005];
int rnk[N];
int root[N];
int croot[N];
int sz = 0, tot = 0;
void insert(int &num, int val, int k, int l, int r);
struct Node {
int sum;
int ch[2];
}T[30500010];
void insert(int &num, int val, int k, int l, int r, int flag) {
if (flag == 0 || num == 0) {
T[++sz] = T[num]; num = sz;
}
T[num].sum += val;
if (l == r) {
return;
}
int m = (l + r) >> 1;
if (k <= m) {
insert(T[num].ch[0], val, k, l, m, flag);
}
else {
insert(T[num].ch[1], val, k, m + 1, r, flag);
}
}
int query(int i, int j, int k, int l, int r) {
if (k > T[j].sum - T[i].sum)
k = T[i].sum - T[i].sum;
if (l == r)
return l;
int m = (l + r) >> 1;
if (k <= T[T[j].ch[0]].sum - T[T[i].ch[0]].sum)
return query(T[i].ch[0], T[j].ch[0], k, l, m);
else
return query(T[i].ch[1], T[j].ch[1], k - (T[T[j].ch[0]].sum - T[T[i].ch[0]].sum), m + 1, r);
}
void add(int x, int num, int d) {
while (x <= tot) {
insert(croot[x], d, num, 1, tot, 1);
x += x&-x;
}
}
struct Pack {
vector<int> v;
Pack() {}
Pack(int x) { v.push_back(x); }
void operator +=(int x) {
v.push_back(x);
}
operator ll()const {//得到左孩子和
ll ret = 0;
for (int i = 0; i<v.size(); i++)
ret += T[T[v[i]].ch[0]].sum;
return ret;
}
void lt() {
for (int i = 0; i < v.size(); i++)
v[i] = T[v[i]].ch[0];
}
void rt() {
for (int i = 0; i < v.size(); i++)
v[i] = T[v[i]].ch[1];
}
};
Pack sum(int x, int k) {
Pack ret;
while (x>0) {
ret += croot[x];
x -= x&-x;
}
return ret;
}
ll binSearch(int l, int r, int k) {
Pack treesl = sum(l,0);
Pack treesr = sum(r,0);
Pack presl = Pack(root[l]);
Pack presr = Pack(root[r]);
int xl = 1, xr = tot;
ll ret = 0;
int rtl = root[l];
int rtr = root[r];
while (xl < xr) {
int mid = (xl + xr) >> 1;
ll t = treesr - treesl + presr - presl;
if (mid <= k) {
ret += t;
treesr.rt(); treesl.rt(); presr.rt(); presl.rt();
//ret += T[T[rtr].ch[0]].sum - T[T[rtl].ch[0]].sum;
xl = mid+1;
if (mid == k) {
ret--;
break;
}
}
else {
treesr.lt(); treesl.lt(); presr.lt(); presl.lt();
xr = mid;
}
}
return ret;
}
struct Seg {
int l, r, h, x;
}q[M];
int val[N];
int cnt = 0;
int Hash(int x) {
return lower_bound(val, val + tot, x) - val + 1;
}
int b[N];
int main() {
//for (int i = 0; i <= sz; i++)T[i] = T[0];
cnt = 0;
sz = 0;
tot = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
a[i] = i;
b[i] = i;
val[cnt++] = a[i];
}
for (int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
if (x > y)
swap(x, y);
q[i * 4].l = x;
q[i * 4].r = y;
q[i * 4].h = b[y];
q[i * 4].x = -1;
q[i * 4 + 1].l = x;
q[i * 4 + 1].r = y;
q[i * 4 + 1].h = b[x];
q[i * 4 + 1].x = -2;
q[i*4+2].x = x;
q[i*4+2].h = b[y];
//val[cnt++] = b[y];
q[i*4+2].l = -inf;
q[i * 4+3].x = y;
q[i * 4+3].h = b[x];
//val[cnt++] = b[x];
q[i * 4+3].l = -inf;
swap(b[x], b[y]);
/*if (l<1 || r>n || l>r || h<1 || h>r - l + 1)
assert(false);*/
}
sort(val, val + cnt);
rnk[0] = ++tot;
for (int i = 1; i < cnt; i++) {
if (val[i] != val[i - 1])
rnk[i] = ++tot;
else
rnk[i] = tot;
}
for (int i = 0; i <= tot; i++)croot[i] = 0;
unique(val, val + cnt);
root[0] = 0;
for (int i = 1; i <= n; i++) {
root[i] = root[i - 1];
insert(root[i], 1, Hash(a[i]), 1, tot, 0);
}
ll ans = 0;
for (int i = 0; i < 4*m; i++) {
if (q[i].l != -inf) {
if (q[i].x == -1) {
if (q[i].l != q[i].r) {
ll tmp = binSearch(q[i].l - 1, q[i].r, Hash(q[i].h));
if (a[q[i].l] < a[q[i].r])
tmp--;
ans += tmp;
ans -= max(0LL, (q[i].r - q[i].l - tmp - 1));
}
//printf("%d\n", val[binSearch(q[i].l - 1, q[i].r, q[i].h) - 1]);
}
if (q[i].x == -2) {
if (q[i].l != q[i].r) {
ll tmp = binSearch(q[i].l - 1, q[i].r, Hash(q[i].h));
if (a[q[i].l] > a[q[i].r])
tmp--;
ans -= tmp;
ans += max(0LL, (q[i].r - q[i].l - tmp - 1));
}
if (a[q[i].l] > a[q[i].r])
ans--;
else if(a[q[i].l]<a[q[i].r])
ans++;
cout << ans << endl;
}
}
else {
add(q[i].x, Hash(a[q[i].x]), -1);
a[q[i].x] = q[i].h;
add(q[i].x, Hash(q[i].h), 1);
}
}
//cout << ans << endl;
/*for (int i = 1; i <= tot; i++)
croot[i] = 0, val[i] = 0, a[i] = 0;*/
return 0;
}
Codeforece E. Anton and Permutation的更多相关文章
- Codeforces785E - Anton and Permutation
Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
- Anton and Permutation
Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input standa ...
- Codeforces 785 E. Anton and Permutation(分块,树状数组)
Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...
- Codeforces 785E. Anton and Permutation
题目链接:http://codeforces.com/problemset/problem/785/E 其实可以CDQ分治... 我们只要用一个数据结构支持单点修改,区间查询比一个数大(小)的数字有多 ...
- [CF785E]Anton and Permutation
题目大意:有一串数为$1\sim n(n\leqslant2\times10^5)$,$m(m\leqslant5\times10^4)$次询问,每次问交换位置为$l,r$的两个数后数列中逆序对的个数 ...
- Codeforces 785E Anton and Permutation(分块)
[题目链接] http://codeforces.com/contest/785/problem/E [题目大意] 一个1到n顺序排列的数列,每次选择两个位置的数进行交换,求交换后的数列的逆序对数 [ ...
- CodeForces 785E Anton and Permutation 分块
题意: 有一个\(1 \sim n\)的排列\(A\),有\(q\)个询问: 交换任意两个元素的位置,求交换之后排列的逆序数 分析: 像这种不太容易用线段树,树状数组维护的可以考虑分块 每\(\sqr ...
- 【codeforces 785E】Anton and Permutation
[题目链接]:http://codeforces.com/problemset/problem/785/E [题意] 给你一个初始序列1..n顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...
随机推荐
- Linux分布式机器 设置机器名字
查看主机的名字: hostname 1.临时修改 [root@localhost datas]# hostname slaver 临时修改,重启服务器后就不生效了 [root@localhost da ...
- 再见HTML ! 用纯Python就能写一个漂亮的网页
我们在写一个网站或者一个网页界面的时候,需要学习很多东西,对小白来说很困难!比如我要做一个简单的网页交互: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在 ...
- C#LeetCode刷题之#225-用队列实现栈(Implement Stack using Queues)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4106 访问. 使用队列实现栈的下列操作: push(x) -- ...
- C#LeetCode刷题之#67-二进制求和(Add Binary)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3929 访问. 给定两个二进制字符串,返回他们的和(用二进制表示) ...
- MySQL InnoDB表空间加密
从 MySQL5.7.11开始,MySQL对InnoDB支持存储在单独表空间中的表的数据加密 .此功能为物理表空间数据文件提供静态加密.该加密是在引擎内部数据页级别的加密手段,在数据页写入文件系统时加 ...
- Newbe.Claptrap 框架如何实现在多种框架之上运行?
Newbe.Claptrap 框架如何实现在多种框架之上运行?最近整理了一下项目的术语表.今天就谈谈什么是 Claptrap Box. 特别感谢 kotone 为本文提供的校对建议! Newbe.Cl ...
- Windows下nacos单机部分发现的坑
一.下载nacos的地址: https://github.com/alibaba/nacos/releases 下载 nacos-server-1.3.2.tar.gz 就好 二.在Window ...
- JavaScript 用七种方式教你判断一个变量是否为数组类型
JavaScript 如何判断一个变量是否为数组类型 引言 正文 方法一 方法二 方法三 方法四 方法五 方法六 方法七 结束语 引言 我们如何判断一个变量是否为数组类型呢? 今天来给大家介绍七种方式 ...
- eclipse及idea使用问题记录(为了方便github同步,重新用Markdown写了一篇)
使用eclipse或idea的时候会遇到各式各样的小问题,解决方案其实网上也大都搜得到,但是下次遇到的时候总是想不起来如何解决,还要花费时间再次查资料.所以以后把遇到的问题都记录一下. @ 目录 Ec ...
- java反序列化——XMLDecoder反序列化漏洞
本文首发于“合天智汇”公众号 作者:Fortheone 前言 最近学习java反序列化学到了weblogic部分,weblogic之前的两个反序列化漏洞不涉及T3协议之类的,只是涉及到了XMLDeco ...