【BZOJ】【3295】【CQOI2011】动态逆序对
树套树
Orz zyf神犇
时光倒流……逆序处理,将删点改为加点,动态维护序列。
由于是动态,要加点,所以用树状数组;同时又需要求序列中求比当前元素大/小的元素个数,所以要用平衡树。
所以方法就是在树状数组的每个节点上维护一棵这个节点表示的区间的平衡树。
为什么这样做是对的呢?因为求<k的元素个数这类操作满足区间加法,所以可以把多棵平衡树上的结果(一棵平衡树表示一个区间)加起来,就是整个区间的结果。
(我一开始想成带修改的区间第K大那种做法了……就是树状数组套权值线段树……sigh)
WA:ans[m+1]需要初始化,样例是因为只剩一个数所以逆序对数为0,但是其他数据明显不会是这样……
/**************************************************************
Problem: 3295
User: Tunix
Language: C++
Result: Accepted
Time:8432 ms
Memory:122372 kb
****************************************************************/ //BZOJ 3295
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
#define CC(a,b) memset(a,b,sizeof(a))
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') sign=-; ch=getchar();}
while(isdigit(ch)) {v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
const double eps=1e-;
typedef long long LL;
/*******************template********************/
int n,m,tot,l[M],r[M],s[M],rnd[M],w[M],v[M];
#define L l[x]
#define R r[x]
inline void Push_up(int x){
s[x]=s[L]+s[R]+w[x];
}
inline void zig(int &x){
int t=L; L=r[t]; r[t]=x; s[t]=s[x]; Push_up(x); x=t;
}
inline void zag(int &x){
int t=R; R=l[t]; l[t]=x; s[t]=s[x]; Push_up(x); x=t;
}
void ins(int &x,int num){
if (!x){
x=++tot; v[x]=num; s[x]=w[x]=; L=R=; rnd[x]=rand(); return;
}
s[x]++;
if (v[x]==num) w[x]++;
else if(num<v[x]){
ins(L,num); if(rnd[L]<rnd[x]) zig(x);
}else{
ins(R,num); if(rnd[R]<rnd[x]) zag(x);
}
}
int rank(int x,int num){//比x小的数有多少个
if (!x) return ;
if (v[x]==num) return s[L];
else if(num<v[x]) return rank(L,num);
else return s[L]+w[x]+rank(R,num);
}
#undef L
#undef R
/**********************Treap********************/
int rt[N];
int ss[N];
void update(int x,int y){
for(int i=x;i<=n;i+=i&-i) ins(rt[i],y);
}
LL getbig(int x,int val){
int t=;
for(int i=x;i;i-=i&-i)
t+=s[rt[i]]-rank(rt[i],val);
return t;
}
LL getsml(int x,int y,int val){
int t1=,t2=;
for(int i=x;i;i-=i&-i)
t1+=rank(rt[i],val);
for(int j=y;j;j-=j&-j)
t2+=rank(rt[j],val);
return t2-t1;
}
void add(int x){
for(int i=x;i<=n;i+=i&-i) ss[i]++;
}
LL sum(int x){
int ans=;
for(int i=x;i;i-=i&-i) ans+=ss[i];
return ans;
}
/*********************Fenwick*******************/
struct data{
int v,pos;
bool operator < (const data&b) const{
return v<b.v;
}
}a[N],b[N],d[N];
LL ans[N];
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
n=getint(); m=getint();
F(i,,n) a[i].v=getint(),a[i].pos=i,b[i]=a[i];
sort(b+,b+n+);
F(i,,m){
d[i].v=getint();
d[i].pos=b[d[i].v].pos;
}
F(i,,n) b[i]=a[i];
F(i,,m) b[d[i].pos].v=;
ans[m+]=; F(i,,n) if (b[i].v){
update(i,b[i].v);
ans[m+]+=sum(n)-sum(b[i].v);
add(b[i].v);
} D(i,m,){
ans[i]=ans[i+]+getbig(d[i].pos-,d[i].v)+getsml(d[i].pos,n,d[i].v);
update(d[i].pos,d[i].v);
}
F(i,,m) printf("%lld\n",ans[i]);
return ;
}
【BZOJ】【3295】【CQOI2011】动态逆序对的更多相关文章
- BZOJ 3295: [Cqoi2011]动态逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3865 Solved: 1298[Submit][Sta ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3295 [题意] n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对. [思路] ...
- 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]
RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...
- BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)
题目大意: 题面传送门 还是一道三维偏序题 每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间 一开始的序列看成n次插入操作 我们先求出不删除时的逆序对总数 ...
- BZOJ 3295 [Cqoi2011]动态逆序对 ——CDQ分治
时间.位置.数字为三个属性. 排序时间,CDQ位置,树状数组处理数字即可. #include <cstdio> #include <cstring> #include < ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- 【Bzoj 3295】 动态逆序对(树套树|CDQ分治)
[题意] 每次删除一个数,然后问删除前逆序对数. [分析] 没有AC不开心.. 我的树状数组套字母树,应该是爆空间的,空间复杂度O(nlogn^2)啊..哭.. 然后就没有然后了,别人家的树套树是树状 ...
随机推荐
- SQL语句统计每天的数据
按用户注册时间统计每天注册的不同来源.不同状态的用户数量: ), RegisterTime, ) RDate ,--DATEPART(YEAR, RegisterTime) 年 ) END 'AWai ...
- C# 线程--第一单线程基础
概念 什么是进程? 当一个程序被打开运行时,它就是一个进程.在进程中包括线程,进程可以由一个或多个线程组成. 什么是线程? 线程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC), ...
- WCF之消息模式
请求/响应:所有操作的默认行为,在WSDL中表现为Input/Output元素. One_Way. 在WSDL中只有Input,没有回应(Output),所以没有异常报告. 单向操作只会在发出调用的瞬 ...
- MySQL 备份和恢复
详细地址:http://imysql.cn/mysql_backup_and_recover
- zedboard 构建嵌入式linux
本文通过五部完成zedboard的嵌入式LINUX搭建,所谓磨刀不五砍材工嘛 1:系统环境搭建 要准备好交叉编译环境 见http://blog.csdn.net/xiabodan/article/de ...
- JVM调优总结 -Xms -Xmx -Xmn -Xss(转载)
堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作 ...
- PHP 登录完成后如何跳转上一访问页面
访问网站页面时,有的页面需要授权才能访问,这时候就会要求用户登录,跳转到登录页面login.php,怎么实现登录后返回到刚才访问的页面 项目需求 访问网站页面时,有的页面需要授权才能访问,这时候就会要 ...
- 简单的下拉刷新以及优化--SwipeRefreshLayout
代码工程简要说明:以一个SwipeRefreshLayout包裹ListView,SwipeRefreshLayout接管ListView的下拉事件,若ListView被用户触发下拉动作后,Swipe ...
- Django模版进阶
# -*- coding: utf-8 -*-from django.shortcuts import renderdef home(request): string = "测试" ...
- openerp - asterisk connector(转载)
原文:http://www.akretion.com/open-source-contributions/openerp-asterisk-voip-connector OpenERP - Aster ...