白白的(baibaide)

有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$,一开始每个位置都是白色。如果一个区间中每个位置都是白色,则称这是一个白白的区间。如果一个白白的区间向左或向右延长后都不是白白的区间了,则称这是一个极长的白白的区间。有 $q$ 次操作,每次操作会修改某个位置的值,或者把某个位置变成黑色。每次操作后,求所有极长的白白的区间中含有的逆序对数的异或和。强制在线。

$n ≤ 150000,q ≤ 20000,0 ≤ a_i ≤ 10^9,1 ≤ x ≤ n,0 ≤ y ≤ 10^9$

$Subtask1(10pts) : n ≤ 10^3, q ≤ 10^3$
$Subtask2(20pts) : 只有 0 操作$
$Subtask3(30pts) : 只有 1 操作$
$Subtask4(40pts) : 没有特殊限制$


Solution

毒题

有种高级的东西叫做启发式分裂,可以应用于只分裂不合并的题目。

每次扫描较小的那一段,复杂度似乎是nlogn的。

那我们考虑每次枚举小的那一段区间的每个数x,然后在大的区间中查找比x大(小)的数的个数,也就是x对于大区间的逆序对贡献。

大区间的答案等于原来区间的答案减去每次查出的答案,小的重新算。

统计小于?主席树就行。修改?树套树。

然而这题没完...

我们算下复杂度:分裂$nlogn$ ,树套树 $nlog^2n$ ,修改 $qlog^2n$

总复杂度 $ nlog^3n + qlog^2n $

n=150000 炸了

我们考虑优化前面的那个^3

按权值为比较大小的关键字建splay

一棵splay维护一段区间,分裂时查询某一段比x大的有几个。

分裂完小的区间暴力重建splay,总共可以有多棵splay

这样前面就是$nlog^2n$了

树套树似乎不用了?然而splay在单点修改时不能维护答案,于是还要。

总复杂度 $ nlog^2n + qlog^2n $

颠覆我对数据结构的认知

 #include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define ll long long
#define maxn 150005
#define Max 1000000000
using namespace std;
int n,q,a[maxn],rt[maxn],tot,cnt,root[maxn];
ll Ans,ans[maxn];
struct no{
int ls,rs,v;
}tr[maxn*];
set<int>dd;
void wh(int k){
tr[k].v=tr[tr[k].ls].v+tr[tr[k].rs].v;
}
void add(int &k,int l,int r,int pl,int v){
if(!k)k=++cnt;
if(l==r){
tr[k].v+=v;
return;
}
int mid=l+r>>;
if(pl<=mid)add(tr[k].ls,l,mid,pl,v);
else add(tr[k].rs,mid+,r,pl,v);
wh(k);
}
ll t_ask(int k,int l,int r,int v,int fl){
if(!k)return ;
ll sl=,sr=;
if(l==r){
return tr[k].v;
}
int mid=l+r>>;
if(fl==){//>v
if(v<=mid)return tr[tr[k].rs].v+t_ask(tr[k].ls,l,mid,v,fl);
else return t_ask(tr[k].rs,mid+,r,v,fl);
}
else{
if(v<=mid)return t_ask(tr[k].ls,l,mid,v,fl);
else return tr[tr[k].ls].v+t_ask(tr[k].rs,mid+,r,v,fl);
}
}
ll ask(int l,int r,int v,int fl){
if(l>r)return ;
ll sl=,sr=;
if(fl)v++;else v--;
if(l->)for(int i=l-;i;i-=i&-i)sl+=t_ask(root[i],,Max,v,fl);
for(int i=r;i;i-=i&-i)sr+=t_ask(root[i],,Max,v,fl);
return sr-sl;
}
ll query(int l,int r,int x){
ll n1=,n2=;
n1=ask(l,x-,a[x],);n2=ask(x+,r,a[x],);
return n1+n2;
}
struct Splay{
int ch[],f,v,num,sz;
}t[maxn*];
void upd(int x){
int ls=t[x].ch[],rs=t[x].ch[];
t[x].sz=t[ls].sz+t[rs].sz+t[x].num;
}
int get(int x){return t[t[x].f].ch[]==x;}
void rotate(int x){
int y=t[x].f,z=t[y].f;
int wx=get(x),wy=get(y);
t[z].ch[wy]=x;t[x].f=z;
t[y].ch[wx]=t[x].ch[wx^];t[t[x].ch[wx^]].f=y;
t[x].ch[wx^]=y;t[y].f=x;
upd(y);upd(x);
}
void splay(int x,int g){
while(t[x].f!=g){
int y=t[x].f,z=t[y].f;
if(z!=g)rotate(get(x)==get(y)?y:x);
rotate(x);
}
}
void modify(int &R,int k,int x,int Num){
int fa=;
while(k&&t[k].v!=x){
fa=k,k=t[k].ch[x>t[k].v];
}
if(k)t[k].num+=Num;
else {
k=++tot;
if(fa)t[fa].ch[x>t[fa].v]=k;
t[k].v=x;t[k].num=t[k].sz=;t[k].f=fa;
}
splay(k,);R=k;
}
ll ask_min(int k,int v){
ll sum=;
while(k){
if(t[k].v<v)sum+=t[t[k].ch[]].sz+t[k].num,k=t[k].ch[];
else if(t[k].v==v){
sum+=t[t[k].ch[]].sz;
break;
}
else k=t[k].ch[];
}
return sum;
}
ll ask_max(int k,int v){//>
ll sum=;
while(k){
if(t[k].v<v)k=t[k].ch[];
else if(t[k].v==v){
sum+=t[t[k].ch[]].sz;
break;
}
else sum+=t[t[k].ch[]].sz+t[k].num,k=t[k].ch[];
}
return sum;
}
int main()
{
cin>>n>>q;dd.insert();dd.insert(n+);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
modify(rt[],rt[],a[i],);
}
for(int i=;i<=n;i++)
for(int j=i;j<=n;j+=j&-j){
add(root[j],,Max,a[i],);
}
for(int i=;i<=n;i++)ans[]+=query(,n,i);
ans[]/=;Ans=ans[];ll la=;
for(int i=,op;i<=q;i++){
scanf("%d",&op);
ll x,y;
if(op==){
scanf("%lld%lld",&x,&y);x^=la;y^=la;
set<int>::iterator it;
it=dd.upper_bound(x);
int r=*it-;it--;int l=*it;
Ans^=ans[l];
ll num=query(l,r,x);
modify(rt[l],rt[l],a[x],-);
ans[l]-=num;
for(int j=x;j<=n;j+=j&-j)add(root[j],,Max,a[x],-);
a[x]=y;
modify(rt[l],rt[l],a[x],);
for(int j=x;j<=n;j+=j&-j)add(root[j],,Max,a[x],);
num=query(l,r,x);
ans[l]+=num;Ans^=ans[l];
printf("%lld\n",Ans);la=Ans;
}
else {
scanf("%lld",&x);x^=la;
set<int>::iterator it;
it=dd.upper_bound(x);
int r=*it-;it--;int l=*it;
Ans^=ans[l];ll co=;
if(x==l){
co=ask_min(rt[l],a[l]);
modify(rt[l],rt[l],a[l],-);
ans[l+]=ans[l]-co;ans[l]=;
rt[l+]=rt[l];rt[l]=;
Ans^=ans[l+];
dd.insert(l+);
}
else if(x==r){
co=ask_max(rt[l],a[r]);
modify(rt[l],rt[l],a[r],-);
ans[l]-=co;Ans^=ans[l];
dd.insert(r);
}
else {
if(x-l<r-x){
for(int i=l;i<=x;i++){
co+=ask_min(rt[l],a[i]);
modify(rt[l],rt[l],a[i],-);
}
ans[x+]=ans[l]-co;
rt[x+]=rt[l];rt[l]=;ans[l]=;
for(int i=l;i<x;i++){
modify(rt[l],rt[l],a[i],);
ans[l]+=ask_max(rt[l],a[i]);
}
Ans=(Ans^ans[l]^ans[x+]);
}
else {
for(int i=r;i>=x;i--){
co+=ask_max(rt[l],a[i]);
modify(rt[l],rt[l],a[i],-);
}
ans[l]-=co;
for(int i=x+;i<=r;i++){
modify(rt[x+],rt[x+],a[i],);
ans[x+]+=ask_max(rt[x+],a[i]);
}
Ans=(Ans^ans[l]^ans[x+]);
}
dd.insert(x);dd.insert(x+);
}
printf("%lld\n",Ans);la=Ans;
}
}
return ;
}

白白的(baibaide)的更多相关文章

  1. 白白的(baibaide)——树状数组套主席树+splay

    题目 [题目描述] 有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$,一开始每个位置都是白色.如果一个区间中每个位置都是白色,则称这是一个白白的区间.如果一个白白的区间向左或 ...

  2. 75道经典AI面试题,我就想把你们安排的明明白白的!(含答案)

    基础知识(开胃菜) Python 1.类继承 有如下的一段代码: class A(object): def show(self): print 'base show' class B(A): def ...

  3. InnoDB:Lock & Transaction

    InnoDB 是一个支持事务的Engine,要保证事务ACID,必然会用到Lock.就像在Java编程一下,要保证数据的线程安全性,必然会用到Lock.了解Lock,Transaction可以帮助sq ...

  4. 【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持

    前言 在之前介绍的流量劫持文章里,曾提到一种『HTTPS 向下降级』的方案 -- 将页面中的 HTTPS 超链接全都替换成 HTTP 版本,让用户始终以明文的形式进行通信. 看到这,也许大家都会想到一 ...

  5. Hibernnate延迟加载策略(这么详细你还看不懂)

    好久没有认真写过博客了,今天就好好的写一篇吧!!!!!!!!! 当Hibernate 从数据库中加载某个对象(例如:Dept对象)时,如果同时自动加载所有的关联的某个对象(例如:Emp对象),而程序实 ...

  6. Bzoj1076 [SCOI2008]奖励关

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1935  Solved: 1053 Description 你正在玩你最喜欢的电子游戏,并且刚刚进入一 ...

  7. 转:入门Webpack,看这篇就够了

    写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过:如果你和十天前的我一样,对很多选项存在着疑惑,那花一段 ...

  8. 使用Windbg在XP下Heap追踪失败的原因

    1.故事背景      最近同事的代码中碰到一个bug会导致奔溃的bug,从dump上看是由于某个对象的堆内存指针被释放了,但代码仍调用了该对象指针的虚函数,从而引起内存访问违法崩溃,由于该类被大量使 ...

  9. C语言初级进阶1

    1.数据类型1.1.基本数据类型数据类型分2类:基本数据类型+复合类型基本类型:char short int long float double复合类型:数组 结构体 共用体 类(C语言没有类,C++ ...

随机推荐

  1. LeetCode-177:第N高的薪水

    第N高的薪水与第二高的薪水,解题思路是一样的,只要对LeetCode-176的SQL做一下变形,便可以满足这题,详见:https://www.cnblogs.com/zouqf/p/10282392. ...

  2. struts2入门第一天----------配置环境

    放假之后有空就开始走上了三大框架的学习.第一个选择的框架是struts2.首先第一步当然是环境的配置.去apache官网把struts2下载下来.然后在自己的开发工具下创建一个web项目.在lib文件 ...

  3. python json.dumps raise TypeError(repr(o) + " is not JSON serializable") TypeError: 0 is not JSON serializable

    出错如题. 这个问题有可能是因为python的json.dumps没法识别dump内容里的某些数据类型导致的.我的问题是因为dict中含有numpy.int64,numpy.float等类型导致的,需 ...

  4. 使用poi将excel转换为html,适用本身有导出excel的而现在需要添加网页打印的功能

    PoiExcelToHtmlUtil.java import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.hssf.usermod ...

  5. Dapper and Repository Pattern in MVC

    大家好,首先原谅我标题是英文的,因为我想不出好的中文标题. 这里我个人写了一个Dapper.net 的Repository模式的底层基础框架. 涉及内容: Dapper.net结合Repository ...

  6. Android+Handler+Thread 那些事儿

    前言,才开始学安卓十几天,不料被线程挡住了前进的步伐,因为之前操作系统课程并没有认真听老师讲课,导致现在理解这些抽象的东西有些小困难.没关系,苦学之路,总会碰到坎坷,这里也给那些迷失在Android之 ...

  7. Java线程和多线程(五)——单例类中的线程安全

    单例模式是最广泛使用的创建模式之一.在现实世界之中,诸如Databae的连接或者是企业信息系统(EIS)等,通常其创建都是受到限制的,应该尽量复用已存在对象而不是频繁创建销毁.为了达到这个目的,开发者 ...

  8. 关于我的Android 博客

    我是曹新雨,我为自己代言.现在的菜鸟,3年以后我就是大神.为自己加油.微信:aycaoxinyu 关于我的Android博客,都是我当初遇到困难,克服之后,写上去的.后来,有人加我微信,问我一些问题, ...

  9. USACO Section2.3 Longest Prefix 解题报告 【icedream61】

    prefix解题报告------------------------------------------------------------------------------------------ ...

  10. Djano之写api使用django_rest_framework【海瑞博客】

    使用django rest framework 可以更快速和友好的编写api,当然网上有很多教程,对于高手来说相对很简单,对于新手来说,根本搞不明白.那是你没有搞明白你自己的职责,做为后端,我们只要提 ...