【ZOJ4053】Couleur(主席树,set,启发式)
题意:
有n个位置,每个位置上的数字是a[i],现在有强制在线的若干个单点删除操作,每次删除的位置都不同,要求每次删除之后求出最大的连续区间逆序对个数
n<=1e5,1<=a[i]<=n
思路:
对于每次删除操作我们可以考虑被删除的数字的贡献
比如区间[l,r]内删除了x这个位置,被分成了[l,x-1]与[x+1,r]两个区间
未删除之前区间总逆序对数可以分为4个部分:[l,x-1]内部,[x+1,r]内部,跨区间,一端为x
一个优秀的结论是内部区间和跨区间部分可以选择两端区间内较小的一段进行暴力枚举计算(启发式),这样每个位置均摊被用到了logn次
然后用总的逆序对数减去其他3部分就是较大区间内部的逆序对数
逆序对部分等价于求某个区间内在[l,r]之间数字的个数,显然使用主席树进行预处理
现在还要维护区间的插入,删除与最大值,这个如果只使用一个splay似乎很难维护多个关键字
大佬new表示并不需要splay,只需要使用set维护被删除的点,就能很快找出被删除的位置处于哪个区间
然而我并不会set,只能照他打一遍了,真是屈辱
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second s
#define MP make_pair
#define N 110000
#define MOD 1000000007
#define eps 1e-8
#define pi acos(-1)
#define oo 1e9 struct node
{
int l,r,s;
}t[N*]; struct data
{
ll x;
int l,r;
}; ll Ans[N],f[N],ans;
int a[N],root[N],cnt,n; set<int>st;
typedef set<int>::iterator iter;
struct setcmp
{
bool operator()(const data &x,const data &y)
{
return x.x>y.x||(x.x==y.x&&x.l<y.l)||(x.x==y.x&&x.l==y.l&&x.r<y.r);
}
};
set<data,setcmp>S; ll query(int l,int r,int x,int y,int L,int R)
{
if(l>r||x>y) return ;
if(x<=l&&r<=y) return t[R].s-t[L].s;
int mid=(l+r)>>;
ll ans=;
if(x<=mid) ans+=query(l,mid,x,y,t[L].l,t[R].l);
if(y>mid) ans+=query(mid+,r,x,y,t[L].r,t[R].r);
return ans;
} void update(int l,int r,int x,int &p)
{
t[++cnt]=t[p];
p=cnt;
t[p].s++;
if(l==r) return;
int mid=(l+r)>>;
if(x<=mid) update(l,mid,x,t[p].l);
else update(mid+,r,x,t[p].r);
} int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} int main()
{
freopen("zoj4053.in","r",stdin);
freopen("zoj4053.out","w",stdout);
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
cnt=;
ans=;
st.clear();
st.insert();
st.insert(n+);
S.clear();
for(int i=;i<=n;i++)
{
root[i]=root[i-];
update(,n,a[i],root[i]);
}
ll ans=;
for(int i=;i<=n;i++) ans+=query(,n,a[i]+,n,root[],root[i-]);
S.insert((data){ans,,n});
f[]=ans;
for(int i=;i<=n;i++)
{
ans=(*S.begin()).x;
Ans[i]=ans;
ll x;
scanf("%lld",&x);
x^=ans;
iter p=st.lower_bound(x);
int r=*p;
p--;
int l=*p;
l++; r--;
S.erase(S.lower_bound((data){f[l],l,r}));
ans=f[l];
ll t1=;
ll t2=;
if(x-l<r-x)
{
for(int i=l;i<x;i++)
{
t1+=query(,n,,a[i]-,root[i],root[x-]);
ans-=query(,n,,a[i]-,root[i],root[r]);
}
ans-=query(,n,,a[x]-,root[x],root[r]);
t2=ans;
}
else
{
for(int i=x+;i<=r;i++)
{
t2+=query(,n,a[i]+,n,root[x],root[i-]);
ans-=query(,n,a[i]+,n,root[l-],root[i-]);
}
ans-=query(,n,a[x]+,n,root[l-],root[x-]);
t1=ans;
}
if(<=x-)
{
S.insert((data){t1,l,x-});
f[l]=t1;
}
if(x+<=r)
{
S.insert((data){t2,x+,r});
f[x+]=t2;
}
st.insert(x);
}
for(int i=;i<n;i++) printf("%lld ",Ans[i]);
printf("%lld\n",Ans[n]); }
return ;
}
【ZOJ4053】Couleur(主席树,set,启发式)的更多相关文章
- 【BZOJ3123】森林(主席树,启发式合并)
题意:一个带点权的森林,要求维护以下操作: 1.询问路径上的点权K大值 2.两点之间连边 n,m<=80000 思路:如果树的结构不发生变化只需要维护DFS序 现在因为树的结构发生变化,要将两棵 ...
- [bzoj3123][Sdoi2013]森林_主席树_启发式合并
森林 bzoj-3123 Sdoi-2013 题目大意:给定一片共n个点的森林,T个操作,支持:连接两个不在一棵树上的两个点:查询一棵树上路径k小值. 注释:$1\le n,T \le 8\cdot ...
- 洛谷 P4755 - Beautiful Pair(主席树+分治+启发式优化)
题面传送门 wssb,我紫菜 看到这类与最大值统计有关的问题可以很自然地想到分治,考虑对 \([l,r]\) 进行分治,求出对于所有 \(l\le x\le y\le r\) 的点对 \((x,y)\ ...
- BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并
题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...
- luoguP3302 [SDOI2013]森林 主席树 启发式合并
题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...
- 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)
传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...
- 白白的(baibaide)——树状数组套主席树+splay
题目 [题目描述] 有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$,一开始每个位置都是白色.如果一个区间中每个位置都是白色,则称这是一个白白的区间.如果一个白白的区间向左或 ...
- bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
随机推荐
- (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql
http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...
- UVA 11324 The Largest Clique (强连通分量,dp)
给出一个有向图,求一个最大的结点集合,任意两个点u,v.u可到达v或v可到达u. 一个强连通分量肯定一起选的.而且只能在一条路径上. 所以先找出所有scc,然后缩点找一条最大权的路径,按拓扑序跑DAG ...
- UVA 10817 - Headmaster's Headache(三进制状压dp)
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&pag ...
- Node.js连接mysql报加密方式错误解决方案
本人在学习全栈开发过程中做一个Node的web项目在连接本地MySQL8.0版本的数据库时,发现Navicat连接不上,它报了一个数据库的加密方式导致连接不上的错误,错误如下: MySQL8.0版本的 ...
- JavaScript判断数组是否包含指定元素的方法
本文实例讲述了JavaScript判断数组是否包含指定元素的方法.分享给大家供大家参考.具体如下: 这段代码通过prototype定义了数组方法,这样就可以在任意数组调用contains方法 /** ...
- a标签目标链接问题
1.先确定开始文件和目标文件,例如从css.html开始到body.html 2.确定文件寻找路径,因为css.html的父目录是css,而body.html在body目录下,所以需要先退到上一目录h ...
- Sql Server 自动备份
1)启动代理服务 服务->Sql server 代理启动 2)设置维护计划 维护计划->设置维护计划向导->修改名称及说明 3)更改计划 4)选择维护任务 5)顺序调整不做解释 6) ...
- Vue的安装并在WebStorm中运行
一.Vue的安装需要两个支持分别为:nodejs.npm Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O ...
- 浅谈倍增LCA
题目链接:https://www.luogu.org/problemnew/show/P3379 刚学了LCA,写篇blog加强理解. LCA(Least Common Ancestors),即最近公 ...
- javaEE(6)_JSP
一.什么是JSP 1.JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术,只用JSP就可以开发动态web资源. 2.为什么J ...