主席树算贡献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的更多相关文章

  1. Codeforces785E - Anton and Permutation

    Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...

  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 ...

  3. Anton and Permutation

    Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input standa ...

  4. Codeforces 785 E. Anton and Permutation(分块,树状数组)

    Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...

  5. Codeforces 785E. Anton and Permutation

    题目链接:http://codeforces.com/problemset/problem/785/E 其实可以CDQ分治... 我们只要用一个数据结构支持单点修改,区间查询比一个数大(小)的数字有多 ...

  6. [CF785E]Anton and Permutation

    题目大意:有一串数为$1\sim n(n\leqslant2\times10^5)$,$m(m\leqslant5\times10^4)$次询问,每次问交换位置为$l,r$的两个数后数列中逆序对的个数 ...

  7. Codeforces 785E Anton and Permutation(分块)

    [题目链接] http://codeforces.com/contest/785/problem/E [题目大意] 一个1到n顺序排列的数列,每次选择两个位置的数进行交换,求交换后的数列的逆序对数 [ ...

  8. CodeForces 785E Anton and Permutation 分块

    题意: 有一个\(1 \sim n\)的排列\(A\),有\(q\)个询问: 交换任意两个元素的位置,求交换之后排列的逆序数 分析: 像这种不太容易用线段树,树状数组维护的可以考虑分块 每\(\sqr ...

  9. 【codeforces 785E】Anton and Permutation

    [题目链接]:http://codeforces.com/problemset/problem/785/E [题意] 给你一个初始序列1..n顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...

随机推荐

  1. 00-基础SQL-SELECT语句

    DML(数据操作语言,增删查改)DDL(数据定义语言,比如创建.修改或删除数据库对象)DCL(数据控制语言,控制数据库的访问) desc 表名:显示表结构:dual : 伪表 对于日期型数据,做 * ...

  2. 如何查看Docker容器环境变量,如何向容器传递环境变量

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 了解Docker容器的运行环境非常重要,我们把应用放在容器里执行,环境变量会直接影响程序的执行效果.所以我们要知道容器内部的 ...

  3. Tomcat Windows 开机自启

    在命令提示符中,进入 tomcat 的 bin 目录,执行命令,注册服务 service.bat install 在"服务"中,将 tomcat 服务设为自动

  4. GitLab 配置模板

    GitLab 配置模板 GitLab 使用模板和参数生成配置文件. 一般来说,我们会通过 gitlab.rb 文件修改配置,例如 Nginx 相关配置. gitlab.rb 只能使用特定的几个 Ngi ...

  5. Weighted-Residual-Connections

  6. Vulnhub靶场-Me and my girlfriend 学习笔记

    靶机下载地址:https://www.vulnhub.com/entry/me-and-my-girlfriend-1,409/ Description: This VM tells us that ...

  7. 刚体验完RabbitMQ?一文带你SpringBoot+RabbitMQ方式收发消息

    人生终将是场单人旅途,孤独之前是迷茫,孤独过后是成长. 楔子 这篇是消息队列RabbitMQ的第二弹. 上一篇的结尾我也预告了本篇的内容:利用RabbitTemplate和注解进行收发消息,还有一个我 ...

  8. windows安装msys2 mingw64

    msys2包含mingw32和mingw64 步骤1 首选安装msys64 链接:https://pan.baidu.com/s/1l9Zfm4TE1Gg3c7tkaH6KeQ 安装到指定目录 步骤2 ...

  9. 使用 .NET Core 3.x 构建 RESTFUL Api (续)

    关于Entity Model vs 面向外部的Model Entity Framework Core 使用 Entity Model 用来表示数据库里面的记录. 面向外部的Model 则表示要传输的东 ...

  10. 基于token的会话保持机制

    session简介 做过Web开发的程序员应该对Session都比较熟悉,Session是一块保存在服务器端的内存空间,一般用于保存用户的会话信息. 用户通过用户名和密码登陆成功之后,服务器端程序会在 ...