luogu1975 [国家集训队]排队
思路
序列中
| i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| a[i] | a | b | c | L | d | e | f | R | g | h |
现逆序对为ans,要交换L,R
则\([1,3],[9,10]\)这两段区间的都不会被他俩影响 (因为L,R和他们相对位置没变啦)
所以现在我们只需要考虑区间\([4,8]\)就好,其他的不考虑在内
一个数对一个区间产生逆序对的贡献为
① 前面大于他的数的个数 (在区间前面)
② 后面小于他的数的个数 (在区间后面)
因为\(L,R\)之间的区间3,6是不变的(废话)
\(L,R\)又在区间两端
那么很显然的
\(ans=ans-(L对区间zz的贡献②)+(L对区间zz的贡献①)-(R对区间zz的贡献①)+(R对区间zz的贡献②)\)
那区间内的贡献咋求啊?
定义不是很明确了吗 就是区间大于x或者小于的个数
\(=>ans-(区间zz内小于L的个数)+(区间zz内大于L的个数)-(区间zz内大于R的个数)+(区间zz内小于R的个数)\)(注意,相等的没有任何贡献)
无脑数据结构呗
随便来个带修主席树 (树状数组套线段树)
复杂度\(nlog^{2}n\)
但常数巨大,更新一次ans要询问8次
错误
都是些zz错误
n写成len
特盘忘记输出ans
代码
//天苍苍,野茫茫,代码怎么这么长
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=1e5+7;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,ans,len,rt[maxn],a[maxn],lsh[maxn],cnt;
int thu[maxn];
struct node {
int ch[2],siz;
}e[maxn*30];
void build(int &now,int old,int l,int r,int k) {
now=++cnt;
e[now]=e[old];
e[now].siz++;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) build(e[now].ch[0],e[old].ch[0],l,mid,k);
else build(e[now].ch[1],e[old].ch[1],mid+1,r,k);
}
void modify(int &now,int l,int r,int k,int gs) {
if(!now) now=++cnt;
e[now].siz+=gs;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) modify(e[now].ch[0],l,mid,k,gs);
else modify(e[now].ch[1],mid+1,r,k,gs);
}
int query1(int now,int l,int r,int k) { //小于mid的数
if(l>=k) return 0;
if(r<k) {
int tot=e[now].siz;
FOR(i,1,thu[0]) tot+=e[thu[i]].siz;
return tot;
}
int mid=(l+r)>>1;
if(k<=mid) {
FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0];
return query1(e[now].ch[0],l,mid,k);
} else {
int tot=e[e[now].ch[0]].siz;
FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[0]].siz;
FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1];
return tot+query1(e[now].ch[1],mid+1,r,k);
}
}
int query2(int now,int l,int r,int k) { //大于mid的数
if(r<=k) return 0;
if(l>k) {
int tot=e[now].siz;
FOR(i,1,thu[0]) tot+=e[thu[i]].siz;
return tot;
}
int mid=(l+r)>>1;
if(k<=mid) {
int tot=e[e[now].ch[1]].siz;
FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[1]].siz;
FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0];
return tot+query2(e[now].ch[0],l,mid,k);
} else {
FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1];
return query2(e[now].ch[1],mid+1,r,k);
}
}
int solve(int l,int r,int k,int pd) {//区间内小于(或小于)k的个数
int tmp=0;
thu[0]=0;
for(int i=r;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n];
tmp+=pd ? query1(rt[r],1,len,k) : query2(rt[r],1,len,k);
thu[0]=0;
for(int i=l-1;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n];
tmp-=pd ? query1(rt[l-1],1,len,k) : query2(rt[l-1],1,len,k);
return tmp;
}
namespace get_init_ans {
int sum[maxn];
void BIT_modify(int x) {
for(int i=x;i<=n;i+=(i&-i)) sum[i]++;
}
int BIT_query(int x) {
int tot=0;
for(int i=x;i>=1;i-=(i&-i)) tot+=sum[i];
return tot;
}
void get_ans() {
for(int i=1;i<=n;++i) {
BIT_modify(a[i]);
ans+=i-BIT_query(a[i]);
}
}
}
using namespace get_init_ans;
int main() {
//read
n=read();
FOR(i,1,n) a[i]=lsh[i]=read();
//lsh and init
sort(lsh+1,lsh+1+n);
len=unique(lsh+1,lsh+1+n)-lsh-1;
FOR(i,1,n) {
a[i]=lower_bound(lsh+1,lsh+1+len,a[i])-lsh;
build(rt[i],rt[i-1],1,len,a[i]);
}
//get_ans
get_ans();
cout<<ans<<"\n";
//work
m=read();
FOR(i_ak_ioi,1,m) {
int x=read(),y=read(),l,l1=0,l2=0,r,r1=0,r2=0;
if(a[x]==a[y]) {
cout<<ans<<"\n";
continue;
}
if(x>y) swap(x,y);
//query
l=x+1,r=y-1;
if(l<=r) {
l2=solve(l,r,a[x],1);
l1=solve(l,r,a[x],0);
r2=solve(l,r,a[y],1);
r1=solve(l,r,a[y],0);
}
//update
ans=ans-l2+l1-r1+r2+(a[x]<a[y] ? 1 : -1);
cout<<ans<<"\n";
//update
for(int i=x;i<=n;i+=(i&-i)) {
modify(rt[i+n],1,len,a[x],-1);
modify(rt[i+n],1,len,a[y],1);
}
for(int i=y;i<=n;i+=(i&-i)) {
modify(rt[i+n],1,len,a[y],-1);
modify(rt[i+n],1,len,a[x],1);
}
swap(a[x],a[y]);
}
return 0;
}
luogu1975 [国家集训队]排队的更多相关文章
- Luogu-1975 [国家集训队]排队
Luogu-1975 [国家集训队]排队 题面 Luogu-1975 题解 题意:给出一个长度为n的数列以及m个交换两个数的操作,问每次操作后逆序对数量 时间,下标和数的大小三维偏序,,,把交换操作看 ...
- 【LG1975】[国家集训队]排队
[LG1975][国家集训队]排队 题面 洛谷 题解 又是一个偏序问题 显然\(CDQ\) 交换操作不好弄怎么办? 可以看成两次删除两次插入 排序问题要注意一下 代码 #include <ios ...
- [国家集训队]排队 [cdq分治]
题面 洛谷 和动态逆序对那道题没有什么区别 把一个交换换成两个删除和两个插入 #include <cstdio> #include <cstdlib> #include < ...
- P1975 [国家集训队]排队
题目链接 题意分析 我们考虑 交换两个数\([le,ri]\)的贡献 减少的逆序对数\([le,ri]\)中小于\(num[le]\)以及大于\(num[ri]\)的数 增加的\([le,ri]\)中 ...
- P1975 [国家集训队]排队 线段树套平衡树维护动态逆序对查询
$ \color{#0066ff}{ 题目描述 }$ 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和. 红星幼儿园的小朋友们排起了长长地队伍 ...
- 洛谷 P1975 [国家集训队]排队 Lebal:块内排序+树状数组
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和. 红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- [luoguP1975] [国家集训队]排队(分块)
传送门 直接暴力分块,然后在每一个块内排序. 查询时可以在每一个块内二分. #include <cmath> #include <cstdio> #include <io ...
- 「Luogu P1975 [国家集训队]排队」
题目大意 给出一个序列 \(h\),支持交换其中的两数,求出每一时刻的逆序对个数. 分析 求逆序对是 \(O(N\log_2N)\) 的,有 \(M\) 个操作,如果暴力求的话时间复杂度就是 \(O( ...
- BZOJ 2039: [2009国家集训队]employ人员雇佣
2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1369 Solved: 667[Submit ...
随机推荐
- 常见web错误码
404表示文件或资源未找到 java WEB常见的错误代码 .1xx-信息提示:这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个1xx响应. -继续. -切换协议. .2xx ...
- MindMaster学习笔记
参考博客 http://blog.sina.com.cn/u/6406591976 作者名叫“MindMaster思维导图的博客 ”写了一系列关于思维导图的博客,可以去学习下. 1.其中有一篇比较详细 ...
- windows编程之Windows Shell 编程
参考书<VC++ Windows Shell Programming> 这里仅仅是记录下该资源,推荐到下文列出的连接进行查看 用VC++ 进行Windows Shell 扩展编成 ...
- 参数化define
SV中的define,可以是对var类型,也可以是对function类型的,或者其他任何可以直接替换的字符. `define wordsize 8 应用 logic [1 :·wordsize] ...
- Python全栈-day1-day2-计算机基础
计算机基础 1.编程语言 语言即事物之间沟通的介质,编程语言即程序员与计算机沟通的介质.程序员通过编写计算机程序使得计算机能够按照人预先的期望执行相应的动作,从而达到在某种程度上解放人和实现人类难以实 ...
- 转:安装PHP出现make: *** [sapi/cli/php] Error 1 解决办法
ext/iconv/.libs/iconv.o: In function `php_iconv_stream_filter_ctor':/home/king/PHP-5.2.13/ext/iconv/ ...
- maven工程的common模块jar上传至仓库并被其它模块依赖
.parent pom和common pom 都需要添加 <distributionManagement> <repository> <id>nexus</i ...
- linux常用命令:ls命令
ls命令是linux下最常用的命令.ls命令就是list的缩写,缺省下ls用来打印出当前目录的清单,如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linux ...
- JVM探秘4---垃圾收集器介绍
Java虚拟机有很多垃圾收集器 下面先来了解HotSpot虚拟机中的7种垃圾收集器:Serial.ParNew.Parallel Scavenge.Serial Old.Parallel Old.CM ...
- 75.Java异常处理机制throws
package testDate; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IO ...