bzoj3295 洛谷P3157、1393 动态逆序对——树套树
题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295
洛谷 P3157(同一道题) https://www.luogu.org/problemnew/show/P3157
洛谷 P1393(略有不同) https://www.luogu.org/problemnew/show/P1393
动态逆序对问题;
树状数组套权值线段树,动态开点;
就像树状数组那样做就可以了,每个线段树维护一段区间内的不同权值的数的个数;
删除一个点,就把答案减去它贡献的逆序对数量就可以了;
有点不太懂空间范围怎么算...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const maxn=1e5+,maxm=maxn*;
int n,m,pos[maxn],t[maxn],rt[maxn],ls[maxm],rs[maxm],sum[maxm],cnt;
ll ans;
ll getsum(int x)
{
ll ret=;
for(;x;x-=(x&-x)) ret+=t[x];
return ret;
}
void add(int x)
{
for(;x<=n;x+=(x&-x)) t[x]++;
}
void update(int &x,int l,int r,int p,int v)
{
if(!x)x=++cnt; sum[x]+=v;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)update(ls[x],l,mid,p,v);
else update(rs[x],mid+,r,p,v);
}
void insert(int x,int p,int v)
{
for(;x<=n;x+=(x&-x)) update(rt[x],,n,p,v);
}
ll ask(int x,int l,int r,int p)
{
if(l==r)return sum[x];
int mid=(l+r)>>;
if(p<=mid)return ask(ls[x],l,mid,p);
return sum[ls[x]]+ask(rs[x],mid+,r,p);
}
ll query(int x,int p)//<=p 的个数
{
ll ret=;
for(;x;x-=(x&-x)) ret+=ask(rt[x],,n,p);
return ret;
}
ll pre(int x,int p){return query(p,n)-query(p,x);}
ll suf(int x,int p){return query(n,x)-query(p,x);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x;i<=n;i++)
{
scanf("%d",&x); pos[x]=i;
ans+=getsum(n)-getsum(x);
add(x); insert(i,x,);
}
for(int i=,x;i<=m;i++)
{
printf("%lld\n",ans); scanf("%d",&x);
ans-=pre(x,pos[x])+suf(x,pos[x]);
insert(pos[x],x,-);
}
return ;
}
洛谷P1393,离散化一下即可。(通过数喜+1)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=4e4+,maxm=maxn*;
int n,m,t[maxn],rt[maxn],ls[maxm],rs[maxm],sum[maxm],cnt,tot;
ll ans,a[maxn],b[maxn];
ll getsum(int x)
{
ll ret=;
for(;x;x-=(x&-x)) ret+=t[x];
return ret;
}
void add(int x)
{
for(;x<=n;x+=(x&-x)) t[x]++;
}
void update(int &x,int l,int r,int p,int v)
{
if(!x)x=++cnt; sum[x]+=v;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)update(ls[x],l,mid,p,v);
else update(rs[x],mid+,r,p,v);
}
void insert(int x,int p,int v)
{
for(;x<=n;x+=(x&-x)) update(rt[x],,n,p,v);
}
ll ask(int x,int l,int r,int p)
{
if(l==r)return sum[x];
int mid=(l+r)>>;
if(p<=mid)return ask(ls[x],l,mid,p);
return sum[ls[x]]+ask(rs[x],mid+,r,p);
}
ll query(int x,int p)//<=p 的个数
{
ll ret=;
for(;x;x-=(x&-x)) ret+=ask(rt[x],,n,p);
return ret;
}
ll pre(int x,int p){return query(p,n)-query(p,x);}
ll suf(int x,int p){return query(n,x)-query(p,x);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i];
sort(b+,b+n+);
tot=unique(b+,b+n+)-b-;
for(int i=;i<=n;i++) a[i]=lower_bound(b+,b+tot+,a[i])-b;
for(int i=;i<=n;i++)
{
ans+=getsum(n)-getsum(a[i]);
add(a[i]); insert(i,a[i],);
}
for(int i=,k;i<=m;i++)
{
printf("%lld ",ans); scanf("%d",&k);
ans-=pre(a[k],k)+suf(a[k],k);
insert(k,a[k],-);
}
printf("%lld\n",ans);
return ;
}
bzoj3295 洛谷P3157、1393 动态逆序对——树套树的更多相关文章
- 洛谷 P3157 [CQOI2011]动态逆序对 解题报告
P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...
- 洛谷 P3157 [CQOI2011]动态逆序对(树套树)
题面 luogu 题解 树套树(树状数组套动态开点线段树) 静态使用树状数组求逆序对就不多说了 用线段树代替树状数组,外面套树状数组统计每个点逆序对数量 设 \(t1[i]\)为\(i\)前面有多少个 ...
- 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治
题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...
- 洛谷P3157 [CQOI2011]动态逆序对
题目大意: 给定\(1\)到\(n\)的一个排列,按照给定顺序依次删除\(m\)个元素,计算每个元素删除之前整个序列的逆序对数量 基本套路:删边变加边 那么我们不就是求满足\(pos_i<pos ...
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
- P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)
P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...
- BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组
BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...
随机推荐
- 使用Hashids来保护你的数据库主键
为什么要保护数据库主键? 数据库主键一般是有序自增主键,极易被爬虫抓取数据,作为应用开发者,这是不应该的,你辛辛苦苦收集的数据转眼之间被其他人给抓取了,是不是很大的损失? Hashids的介绍 gen ...
- 集训第四周(高效算法设计)E题 (区间覆盖问题)
UVA10382 :http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21419 只能说这道题和D题是一模一样的,不过要进行转化, ...
- NRF24L01注意点
nrf24L01被设置为接收模式后,可通过6个不同的数据通道(data pipe)接收数据. 每个数据通道都有一个唯一的地址但是各数据通道的频率是相同的.这意味着可以有6个被配置成发送状态的nRF24 ...
- FZU Problem 2171 防守阵地 II (线段树区间更新模板题)
http://acm.fzu.edu.cn/problem.php?pid=2171 成段增减,区间求和.add累加更新的次数. #include <iostream> #include ...
- ZOJ 1298_Domino Effect
题意: 多米诺骨牌效应:若干个关键牌相连,关键牌之间含有普通牌,关键牌倒下后其所在的行的普通牌全部倒下.求从推倒1号关键牌开始,最终倒下的牌的位置及时间. 分析: 最终倒下的牌的位置有两种情况,要么是 ...
- spring boot file上传
用Spring Boot写读取Excel文件小工具的时候遇到的一些小坑已经填平,复制即可满足普通的文件上传功能POI方面只需一个包,其他通用包工程中一般都会带TIPS:前端为了扩展我用ajax异步请求 ...
- 联想M7400打印机加粉墨了还是显示没有粉墨
联想M7400打印机加粉墨了还是显示没有粉墨?想必有很多的办公人士发现这个难题吧.其实很简单的! 先说下打印机的原理,打印机粉墨一边用的时候系统也在计数,当我们打印机加好墨后但打印机是不知道已经加好 ...
- C++进阶之虚函数表
C++通过继承(inheritance)和虚函数(virtual function)来实现多态性.所谓多态,简单地说就是,将基类的指针或引用绑定到子类的实例,然后通过基类的指针或引用调用实际子类的成员 ...
- Python爬虫(一):基本概念
网络爬虫的定义 网络爬虫(Web Spider.又被称为网页蜘蛛.网络机器人,又称为网页追逐者),是一种依照一定的规则,自己主动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字 ...
- 在C++代码中调用L脚本语言
L脚本语言同意被其他编程语言调用.如C++,非常easy.仅仅要在宿主语言中载入L脚本引擎的动态库 直接调用这两个函数就能够了 extern "C" int __stdcall S ...