【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重建一下 注意 测试点 ...
随机推荐
- python读取.mat文件
可以先看一下.mat中存了些什么: import scipy.io as sio box_file = '/home/bnrc/formatm/test/1479504458876408533_box ...
- 搭建SSI开发框架原理
Spring2.5.Struts2.Ibatis开发框架搭建(一) ssi, ibatis 一.框架下载 1.1 Struts2框架 Struts2框架发展于WebWork,现在捐献给了Apach ...
- 用jquery操作xml文件
一. xml文件\内容读取 1.读取xml文件 $.get( xmlfile.xml , function (xml){ //xml即为可以读取使用的内容,具体读取见第2点 }); 2.读取xml内容 ...
- tp5对接支付宝支付简单集成
对于每个刚开始工作的新手来说,无论支付宝支付还是微信支付都是跑不掉的一个小门槛. 在加上本人比较技术比较渣(比较懒导致的),不太喜欢引用那么大的SDK,于是就简单集成了一下支付宝的支付. 但也只是只有 ...
- java在线聊天项目 swt可视化窗口Design 登录框注册按钮点击改变窗口大小——出现注册面板 实现打开登录框时屏幕居中
登录框注册按钮点击改变窗口大小——出现注册面板 首先用swt可视化设计登录窗口如下图: 此时窗口高度为578 没点击注册时高度为301(可自己定) 注意:注册用户的Jpanel 的border选择T ...
- ASIHTTPRequest简单学习
ASIHTTPRequest框架是优秀的第三方Objective-C的HTTP框架,支持Mac OS X和iOS下的HTTP开发. 一.ASIHTTPRequest框架的安装和配置 (1)首先要在项目 ...
- js最高效的数组去重方法
var arr=[1,2,33,2,4,5,33,5,7,8,1,3];var result=[];var temp={};for( var i=0;i<arr.length;i++){ if( ...
- redux form
纯粹使用react进行表单校验: class MyForm extends React.Component{ constructor(props){ super(props) this.onAddrC ...
- vue中 表头th 合并单元格,且表格列数不定的动态渲染方法
吐槽 今天,在vue中遇到 复杂表格的渲染 ,需要合并表头的单元格,且合并单元格的那列还是动态数据,也就是说你不知道会有多少组要合并起来,哎,我也有点说不清楚,废话不多说了,看代码把: 代码示例 da ...
- 利用js实现图片展开与收缩
1.元素居中放大: 1>除了要改变元素的宽高以外,还要改变元素的定位(left,top),如果图片放大一倍,那么位移放大宽高的一半. 2>元素必须是定位的.所以,在css中设置为浮动布局, ...