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顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...
随机推荐
- Xposed原理分析
目录 安卓系统启动 什么zygote? 安卓应用运行? Xposed介绍 Xposed构成 Xposed初始化大体工作流程 源码分析 初始化 app_main#main app_main#initia ...
- go微服务系列(一) go micro入门
1. 什么是go micro 1.1 go micro作用 1.2 go micro架构组成 2. go micro入门 3. 结合consul进行服务注册/发现 3.1 consul的安装 3.2 ...
- 93复原IP地址。
from typing import List# 这道题不是很难,但是限制条件有很多.# 用递归的方法可以很容易的想到.只需要四层递归就好了.# 每次进行加上限制条件.过滤每一层就好了..class ...
- C#设计模式之8-组合模式
组合模式(Composite Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/403 访问. 组合模式属 ...
- Golang gRPC学习(03): grpc官方示例程序route_guide简析
代码主要来源于grpc的官方examples代码: route_guide https://github.com/grpc/grpc-go/tree/master/examples/route_gui ...
- 为什么?为什么?Java处理排序后的数组比没有排序的快?想过没有?
先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个有颜值却假装靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题 ...
- Ubuntu操作系统(文件传输)
首先选择Ubuntu版本为偶数版本--(系统比较稳定软件源比较齐全) Ubuntu和windows之间的文件传输首先在Windows上安装连接工具winscp 在Ubuntu开启SSH服务(https ...
- java多线程:线程同步synchronized(不同步的问题、队列与锁),死锁的产生和解决
0.不同步的问题 并发的线程不安全问题: 多个线程同时操作同一个对象,如果控制不好,就会产生问题,叫做线程不安全. 我们来看三个比较经典的案例来说明线程不安全的问题. 0.1 订票问题 例如前面说过的 ...
- django自带orm妙用
django对数据库数据进行处理方式通常有以下几种方式: 1.使用原生sql对数据库进行处理:pymysql,cx_oracle 2.使用外置orm模块来对数据库进行处理:sqlalchemy 3.使 ...
- 使用pip安装模块,出现Cannot unpack file xxx的问题的解决
在windows下使用pip 豆瓣源安装gevent时出现错误 解决办法: pip install -i https://pypi.douban.com/simple/ --trusted-host ...