【bzoj3295】动态逆序对

我怎么控制不住自己又写了个数据结构啊……真是的……

其实我是想练CDQ分治的……结果忍不住又写了个主席树。

首先看看不动态的逆序对咋做?树状数组嘛。

那么删除咋搞?就是考虑贡献,把它前面比他大的,后面比他小的减去……

诶?带修改主席树?我……我好像才写过……?

 1 #include<bits/stdc++.h>
 2 #define inf 0x7fffffff
 3 #define N 100005
 4 #define M 5000005
 5 using namespace std;
 6 typedef long long ll;
 7 ll ans;
 8 int n,m,sz,a[100],b[100],val[N],pos[N],a1[N],a2[N];
 9 int c[N*10],rt[N],ls[M],rs[M],sumv[M];
10 inline int lowbit(int x){return x&(-x);}
11 inline int ask(int x){
12     int ans=0;
13     for(int i=x;i;i-=lowbit(i))ans+=c[i];
14     return ans;
15 }
16 void change(int &o,int l,int r,int q){
17     if(!o)o=++sz;sumv[o]++;
18     if(l==r)return;
19     int mid=(l+r)>>1;
20     if(q<=mid)change(ls[o],l,mid,q);
21     else change(rs[o],mid+1,r,q);
22 }
23 int querysub(int x,int y,int v){
24     int cnta=0,cntb=0;int ans=0;x--;
25     for(int i=x;i;i-=lowbit(i))a[++cnta]=rt[i];
26     for(int i=y;i;i-=lowbit(i))b[++cntb]=rt[i];
27     int l=1,r=n;
28     while(l!=r){
29         int mid=(l+r)>>1;
30         if(v<=mid){
31             for(int i=1;i<=cnta;i++)ans-=sumv[rs[a[i]]];
32             for(int i=1;i<=cntb;i++)ans+=sumv[rs[b[i]]];
33             for(int i=1;i<=cnta;i++)a[i]=ls[a[i]];
34             for(int i=1;i<=cntb;i++)b[i]=ls[b[i]];
35             r=mid;
36         }
37         else{
38             for(int i=1;i<=cnta;i++)a[i]=rs[a[i]];
39             for(int i=1;i<=cntb;i++)b[i]=rs[b[i]];
40             l=mid+1;
41         }
42     }
43     return ans;
44 }
45 int querypre(int x,int y,int v){
46     int cnta=0,cntb=0,ans=0;x--;
47     for(int i=x;i;i-=lowbit(i))a[++cnta]=rt[i];
48     for(int i=y;i;i-=lowbit(i))b[++cntb]=rt[i];
49     int l=1,r=n;
50     while(l!=r){
51         int mid=(l+r)>>1;
52         if(v>mid){
53             for(int i=1;i<=cnta;i++)ans-=sumv[ls[a[i]]];
54             for(int i=1;i<=cntb;i++)ans+=sumv[ls[b[i]]];
55             for(int i=1;i<=cnta;i++)a[i]=rs[a[i]];
56             for(int i=1;i<=cntb;i++)b[i]=rs[b[i]];
57             l=mid+1;
58         }
59         else{
60             for(int i=1;i<=cnta;i++)a[i]=ls[a[i]];
61             for(int i=1;i<=cntb;i++)b[i]=ls[b[i]];
62             r=mid;
63         }
64     }
65     return ans;
66 }
67 inline int read(){
68     int f=1,x=0;char ch;
69     do{ch=getchar();if(ch==‘-‘)f=-1;}while(ch<‘0‘||ch>‘9‘);
70     do{x=x*10+ch-‘0‘;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘);
71     return f*x;
72 }
73 int main(){
74     n=read();m=read();
75     for(int i=1;i<=n;i++){
76         val[i]=read();pos[val[i]]=i;
77         a1[i]=ask(n)-ask(val[i]);
78         ans+=a1[i];
79         for(int j=val[i];j<=n;j+=lowbit(j))c[j]++;
80     }
81     memset(c,0,sizeof(c));
82     for(int i=n;i;i--){
83         a2[i]=ask(val[i]-1);
84         for(int j=val[i];j<=n;j+=lowbit(j))c[j]++;
85     }
86     for(int i=1;i<=m;i++){
87         printf("%lld\n",ans);
88         int x=read();x=pos[x];
89         ans-=(a1[x]+a2[x]-querysub(1,x-1,val[x])-querypre(x+1,n,val[x]));
90         for(int j=x;j<=n;j+=lowbit(j))change(rt[j],1,n,val[x]);
91     }
92     return 0;
93 }

感觉在写数据结构就要数据结构上瘾综合症了。

业界俗称 数据结构学傻

顺便纪念一下bzoj200AC。

时间: 2024-08-06 21:33:16

【bzoj3295】动态逆序对的相关文章

bzoj3295动态逆序对

Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5362  Solved: 1814[Submit][Status][Discuss] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数

BZOJ3295 动态逆序对 树套树, 树状数组套线段树(主席树)

Orz黄学长,蒟蒻在黄学长的带领下,通过阅读黄学长的代码!终于会了这道题! 首先我想先说一下这道题的思路(准确来说是黄学长的). 很明显,树状数组应该不用讲吧!关键是内存怎么开,维护一些什么样的数据? 其实我们通过观察,很快可以发现,你维护被删的数比维护所有的数轻松多了(不管是空间上,还是时间上).所以我们就可以从这方面想!(其实我一开始的思路,因为这道题我已经看过很久了,一直想写,毕竟是白书里面的一道例题嘛!一开始,蒟蒻的我是打算这样的用树状数组套权值线段树,并且是维护所有的数,我发现空间不够

【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治

[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的

bzoj3295【CQOI2011】动态逆序对

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3122  Solved: 986 [Submit][Status][Discuss] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数

[CQOI2011]动态逆序对

P1347 - [CQOI2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数. 以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个

主席树初探 &amp; bzoj 3295: [Cqoi2011] 动态逆序对 题解

[原题] 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 778  Solved: 263 [Submit][Status] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元

Bestcoder7(1004)hdu4988(经典问题:树状数组套treap求解动态逆序对)

Little Pony and Boast Busters Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 83    Accepted Submission(s): 32 Problem Description "I hereby challenge you, Ponyvillians: anything you can do

【BZOJ 3295】 [Cqoi2011]动态逆序对

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1373  Solved: 465 [Submit][Status][Discuss] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数

【Luogu1393】动态逆序对(CDQ分治)

[Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序列的逆序对组数及其删去其中的某个数的逆序对组数. 输入输出格式 输入格式: 第一行,两个数n,m,表示序列中有n个数,要删去m个数 第二行n个数,表示给定的序列. 第三行m个数,第i个数di表示要删去原序列中的第di个数. 输出格式: 一行m+1个数.第一个数表示给定序列的逆序对组数,第i+1个数表示删去第d

【算法】CDQ分治 -- 三维偏序 &amp; 动态逆序对

初次接触CDQ分治,感觉真的挺厉害的. 整体思路即分而治之,再用之前处理出来的答案统计之后的答案. 大概流程是: 对于区间 l ~ r : 1.处理 l ~mid, mid + 1 ~ r 的答案 2.分别排序规整 3.计算 l ~ mid 中每一个数对 mid + 1 ~ r 中的答案的贡献, 累加 4.得到区间l ~ r的答案 CDQ分治我一共也才做了两道题目, 就一起整理在这里了.大体都差不多,CDQ+树状数组分别维护两个维度. 1.三维偏序 #include <bits/stdc++.h