【题意】

  每次删除一个数,然后问删除前逆序对数。

【分析】

  没有AC不开心。。

  我的树状数组套字母树,应该是爆空间的,空间复杂度O(nlogn^2)啊。。哭。。

  然后就没有然后了,别人家的树套树是树状数组套平衡树,O(nlogn)的啊。。

  别人家的CDQ分治更屌。。我垃圾咯。

只是存个代码:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 200010
#define Maxd 31 int a[Maxn],wr[Maxn];
int n,m; struct node
{
int son[],cnt;
}tr[Maxn**];int tot; void upd(int x)
{
tr[x].son[]=tr[x].son[]=;
tr[x].cnt=;
} void add(int now,int y,int c)
{
for(int i=Maxd;i>=;i--)
{
int ind=y>>i-;
y=y%(<<i-);
if(!tr[now].son[ind])
{
tr[now].son[ind]=++tot;
upd(tot);
}
now=tr[now].son[ind];
tr[now].cnt+=c;
}
} int ffind(int now,int y)
{
int ans=;
for(int i=Maxd;i>=;i--)
{
int ind=y>>i-;
y=y%(<<i-);
if(ind==)
{
ans+=tr[tr[now].son[]].cnt;
now=tr[now].son[];
}
else now=tr[now].son[];
}
return ans;
} int sm[Maxn];
void change(int x,int y,int c)
{
for(int i=x;i<=n;i+=i&(-i))
add(i,y,c),sm[i]+=c; } int ad;
int query(int x,int y)
{
ad=;
int ans=;
for(int i=x;i>=;i-=i&(-i))
ad+=sm[i],ans+=ffind(i,y);
return ans;
} int main()
{
int ans=;
scanf("%d%d",&n,&m);
memset(sm,,sizeof(sm));
for(int i=;i<=n;i++) {scanf("%d",&a[i]);wr[a[i]]=i;}
upd();
tot=n;
for(int i=;i<=n;i++)
{
ans+=query(i-,a[i]);
change(i,a[i],);
}
int sum=n;
for(int i=;i<=m;i++)
{
int x;
scanf("%d",&x);
printf("%d\n",ans);
sum--;
change(wr[x],x,-);
int now=-query(n,x);
now+=*query(wr[x]-,x);
ans-=sum+now-ad;
}
return ; }

2016-11-08 16:42:22


学了cdq分治回来更新耶!!

用CDQ分治AC啦哈哈~~

CDQ分治比树套树省空间多了,空间是O(n)的,时间还是O(nlogn^2)

然后,简单说一下?

我自己也不是很懂,刚会。。

Solve(l,r)为求出区间l~r的答案。

然后只有编号小于它的对他有影响。

然后二分 [l,mid]和[mid+1,r],,考虑完[l,mid]对[mid+1,r]的影响之后,那两个区间就可以分开搞了。(就是分治)

问题变成快速求[l,mid]对[mid+1,r]的影响。

本题中,我们可以看成是一个三元组i->(xi,yi,zi),然后ans[i]=x<xi y<yi z>zi或者x<xi y>yi z<zi 的数量。。

x这一维是时间戳,y是编号,z是值(想一想就知道他为什么表示逆序对啦!!!)

那么,只有x<xi的对xi有影响,把x这一维作为编号。

快速求出,[l,mid]对[mid+1,r]中y<yi z>zi或者y>yi z<zi 的数量

可以用y排序,树状数组维护,求和,就知道y和z的逆序对数了。。

n元组,满足x>xi,y>yi....的个数的东东 。。【这东西叫n维偏序???好像是CDQ分治的经典题哦!!

啊。。。WA了好久,竟然是没有开LL!!!!好傻啊、、

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 200010
#define LL long long int a[Maxn],b[Maxn];
LL f[Maxn];
int n,m; int c[Maxn];
bool vis[Maxn]; struct node
{
int x,y,id;
}t[Maxn];int tl; int mymax(int x,int y) {return x>y?x:y;}
bool cmp(node x,node y) {return x.x>y.x;}
bool cmp2(node x,node y) {return x.x<y.x;} void add(int x,int y)
{
for(int i=x;i<=n;i+=i&(-i))
c[i]+=y;
} int query(int x)
{
int ans=;
for(int i=x;i>=;i-=i&(-i))
ans+=c[i];
return ans;
} void solve2(int l,int r)
{
tl=;
for(int i=l;i<=r;i++)
{
t[++tl].x=a[i];
t[tl].y=b[i];
t[tl].id=i;
}
sort(t+,t++tl,cmp);
for(int i=;i<=tl;i++)
{
if(vis[t[i].id]) f[t[i].id]+=query(t[i].y);
else add(t[i].y,);
}
for(int i=;i<=tl;i++) if(!vis[t[i].id]) add(t[i].y,-);
sort(t+,t++tl,cmp2);
for(int i=;i<=tl;i++)
{
if(vis[t[i].id]) f[t[i].id]+=query(n-t[i].y+);
else add(n-t[i].y+,);
}
for(int i=;i<=tl;i++) if(!vis[t[i].id]) add(n-t[i].y+,-);
} void solve(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>;
for(int i=l;i<=mid;i++) vis[i]=;
for(int i=mid+;i<=r;i++) vis[i]=;
solve2(l,r);
solve(l,mid);solve(mid+,r);
} int wr[Maxn],d[Maxn];
void init()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
wr[x]=i;
}
for(int i=n;i>n-m;i--)
{
int x;
scanf("%d",&x);
a[i]=x;
b[i]=wr[x];
wr[x]=;
}
int now=n-m+;
for(int i=;i<=n;i++) if(wr[i]!=) a[--now]=i,b[now]=wr[i];
memset(c,,sizeof(c));
memset(f,,sizeof(f));
} int main()
{
init();
solve(,n);
LL ans=;
for(int i=;i<=n;i++) ans+=f[i];
for(int i=n;i>n-m;i--)
{
printf("%lld\n",ans);
ans-=f[i];
}
return ;
}

代码还不是很长啦,主要是CDQ分治空间真的要小很多。。

所以才知道,为什么大神说树套树粉转路人了ORZ。。。

2016-11-08 20:14:57

【Bzoj 3295】 动态逆序对(树套树|CDQ分治)的更多相关文章

  1. BZOJ 3295 动态逆序对 | CDQ分治

    BZOJ 3295 动态逆序对 这道题和三维偏序很类似.某个元素加入后产生的贡献 = time更小.pos更小.val更大的元素个数 + time更小.pos更大.val更小的元素个数. 分别用类似C ...

  2. bzoj 3295 动态逆序对 (三维偏序,CDQ+树状数组)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3295 思路: 可以将这道题看成倒着插入,这样就可以转化成求逆序对数,用CDQ分治降维,正反用 ...

  3. BZOJ - 3295 动态逆序对 (树状数组套treap)

    题目链接 思路和bzoj2141差不多,不过这道题的数据更强一些,线段树套treapT了,树状数组套treap卡过~~ #include<bits/stdc++.h> using name ...

  4. BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那 ...

  5. bzoj 3295 动态逆序对 CDQ分支

    容易看出ans[i]=ans[i-1]-q[i],q[i]为删去第i个数减少的逆序对. 先用树状数组算出最开始的逆序对,预处理出每个数前边比它大的和后边比它小的,就求出了q[i]的初始值. 设b[i] ...

  6. BZOJ 3295 动态逆序对

    调了好久.... 转化成三维偏序,cdq处理. 好像比较快? #include<iostream> #include<cstdio> #include<cstring&g ...

  7. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  8. [bzoj3295][Cqoi2011]动态逆序对_主席树

    动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...

  9. bzoj3295 洛谷P3157、1393 动态逆序对——树套树

    题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...

  10. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

随机推荐

  1. Manually connecting to the Oracle Linux Yum Server

    Manually connecting to the Oracle Linux Yum Server 1. Download and Install Oracle Linux   Note: The ...

  2. Orcle11g用户密码恢复

    1.当安装Orcle11g后,很久不用,忘记了用户名和密码.可以通过以下方法重置: 如上图及重置用户sys,system密码为123

  3. poj 1007 DNA Sorting

    DNA Sorting Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 95437   Accepted: 38399 Des ...

  4. NUnit使用详解(二)

    转载:http://hi.baidu.com/grayworm/item/39aa11c5d9375d56bdef6990 五:常用断言 在NUnit中,断言是单元测试的核心.NUnit提供了一组丰富 ...

  5. 20151210 Jquery 学习笔记 AJAX 进阶

    一.加载请求 在 Ajax 异步发送请求时,遇到网速较慢的情况,就会出现请求时间较长的问题.而超 过一定时间的请求,用户就会变得不再耐烦而关闭页面.而如果在请求期间能给用户一些提 示,比如:正在努力加 ...

  6. css层叠顺序

    优先级: 1.添加!important规则的分组享有最高优先级:会将所有不带!important的规则 例如:#id{border:6px solid black!important}高于#id{bo ...

  7. ZOJ 1013 Great Equipment(DP)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=13 题目大意:说的是有三种不同的装备,分别是头盔,盔甲,战靴需要运输, ...

  8. C++中string类型对象和double型变量之间的互相转换

    //convert string type value to double type value string s = "23"; double d; istringstream ...

  9. git ignore已经checked in files

    对于untracked file, 可以使用.gitignore 对于已经checked in file,可以使用git update-index #隐藏 git update-index --ass ...

  10. 【原创】Linux下获取命令的帮助与常用命令

    Linux中的shell命令一般是执行步骤:用户在终端输入命令回车,系统内核会在当前用户的环境变量PATH中去读取环境变量的值 变量的值就是命令的路径,命令路径不只一个,于是系统会从这些路径中从左至右 ...