bzoj 3295 (洛谷3157、3193) [Cqoi2011]动态逆序对——树套树 / CDQ分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3295
题目--洛谷3157:https://www.luogu.org/problemnew/show/P3157
题目--洛谷3193:https://www.luogu.org/problemnew/show/P1393
1.树状数组套权值线段树
有点卡空间。线段树节点的*100怎么算?
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+;
int n,m,f[N],rt[N],tot,ps[N];
ll ans;
struct Node{
int ls,rs,sum;
}a[N*];
int getsm(int x)
{
int ret=;for(;x;x-=(x&-x))ret+=f[x];return ret;
}
void addsm(int x)
{
for(;x<=n;x+=(x&-x))f[x]++;
}
void insert(int &cr,int l,int r,int p,int fx)
{
if(!cr)cr=++tot;a[cr].sum+=fx;
if(l==r)return;
int mid=((l+r)>>);
if(p<=mid)insert(a[cr].ls,l,mid,p,fx);
else insert(a[cr].rs,mid+,r,p,fx);
}
void insert(int x,int v,int fx)
{
for(;x<=n;x+=(x&-x))insert(rt[x],,n,v,fx);
}
int query(int cr,int l,int r,int x)
{
if(r<=x)return a[cr].sum;
int mid=((l+r)>>);
if(x<=mid)return query(a[cr].ls,l,mid,x);
return a[a[cr].ls].sum+query(a[cr].rs,mid+,r,x);
}
int query(int x,int v)
{
int ret=;for(;x;x-=(x&-x))ret+=query(rt[x],,n,v);return ret;
}
int pre(int p,int x)
{
return query(p,n)-query(p,x);
}
int suf(int p,int x)
{
return query(n,x)-query(p,x);
}
int main()
{
scanf("%d%d",&n,&m);int x;
for(int i=;i<=n;i++)
{
scanf("%d",&x);ans+=getsm(n)-getsm(x);
addsm(x);insert(i,x,);ps[x]=i;
}
for(int i=;i<=m;i++)
{
printf("%lld\n",ans);scanf("%d",&x);
ans-=pre(ps[x],x)+suf(ps[x],x);
insert(ps[x],x,-);
}
return ;
}
加上离散化就能过洛谷3193了。通过数喜+1。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=4e4+;
int n,m,f[N],rt[N],tot,vl[N];
ll ans,tp[N],t[N];
struct Node{
int ls,rs,sum;
}a[N*];
int getsm(int x)
{
int ret=;for(;x;x-=(x&-x))ret+=f[x];return ret;
}
void addsm(int x)
{
for(;x<=n;x+=(x&-x))f[x]++;
}
void insert(int &cr,int l,int r,int p,int fx)
{
if(!cr)cr=++tot;a[cr].sum+=fx;
if(l==r)return;
int mid=((l+r)>>);
if(p<=mid)insert(a[cr].ls,l,mid,p,fx);
else insert(a[cr].rs,mid+,r,p,fx);
}
void insert(int x,int v,int fx)
{
for(;x<=n;x+=(x&-x))insert(rt[x],,n,v,fx);
}
int query(int cr,int l,int r,int x)
{
if(r<=x)return a[cr].sum;
int mid=((l+r)>>);
if(x<=mid)return query(a[cr].ls,l,mid,x);
return a[a[cr].ls].sum+query(a[cr].rs,mid+,r,x);
}
int query(int x,int v)
{
int ret=;for(;x;x-=(x&-x))ret+=query(rt[x],,n,v);return ret;
}
int pre(int p,int x)
{
return query(p,n)-query(p,x);
}
int suf(int p,int x)
{
return query(n,x)-query(p,x);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lld",&t[i]),tp[i]=t[i];
sort(tp+,tp+n+);int cnt=unique(tp+,tp+n+)-tp-;
for(int i=;i<=n;i++)vl[i]=lower_bound(tp+,tp+cnt+,t[i])-tp;
for(int i=;i<=n;i++)
{
ans+=getsm(n)-getsm(vl[i]);
addsm(vl[i]);insert(i,vl[i],);
}
printf("%lld ",ans);int x;
for(int i=;i<=m;i++)
{
scanf("%d",&x);
ans-=pre(x,vl[x])+suf(x,vl[x]);
insert(x,vl[x],-);printf("%lld ",ans);
}
return ;
}
2.CDQ分治
学习TJ。https://www.cnblogs.com/candy99/p/6440745.html
1)先按位置排序,再按时间分治。
2)把影响加到树状数组里。往下递归之前先撤销修改。
3)应该是空间n+m,时间 (n+m) * log(n) * log(n)。(一个log分治,一个log树状数组,(n+m)是每一层的操作次数)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+,M=5e4+;
int n,m,tot,pos[N],f[N]; //树状数组是值
ll ans[M];
struct Cz{
int t,ps,v,id,type;
Cz(int t=,int p=,int v=,int i=,int y=):t(t),ps(p),v(v),id(i),type(y) {}
bool operator<(const Cz k)const
{
return ps<k.ps;
}
}a[N+M],tp[N+M];
void add(int x,int v)
{
for(;x<=n;x+=(x&-x))f[x]+=v;
}
int query(int x)
{
int ret=;for(;x;x-=(x&-x))ret+=f[x];return ret;
}
void CDQ(int l,int r) //l,r是时间,也已经是角标
{
if(l==r)return;
int mid=((l+r)>>);
for(int i=l;i<=r;i++)
if(a[i].t<=mid)add(a[i].v,a[i].type);
else ans[a[i].id]+=a[i].type*(query(n)-query(a[i].v)); //在我前面、比我大的
for(int i=l;i<=r;i++) if(a[i].t<=mid)add(a[i].v,-a[i].type); //撤销操作,不影响递归下去 for(int i=r;i>=l;i--)
if(a[i].t<=mid)add(a[i].v,a[i].type);
else ans[a[i].id]+=a[i].type*query(a[i].v-); //在我后面、比我小的
for(int i=r;i>=l;i--) if(a[i].t<=mid) add(a[i].v,-a[i].type); //撤销操作 int p0=l,p1=mid+;
for(int i=l;i<=r;i++)
if(a[i].t<=mid)tp[p0++]=a[i]; //去左边/右边,但没有改变相对位置。
else tp[p1++]=a[i]; //即一开始的按位置排序效果还在
for(int i=l;i<=r;i++)a[i]=tp[i];
CDQ(l,mid);CDQ(mid+,r);
}
int main()
{
scanf("%d%d",&n,&m);int x;
for(int i=;i<=n;i++)
{
scanf("%d",&x);pos[x]=i;
a[++tot]=Cz(tot,i,x,,);
}
for(int i=;i<=m;i++)
{
scanf("%d",&x);
a[++tot]=Cz(tot,pos[x],x,i,-);
}
sort(a+,a+tot+);
CDQ(,tot);
for(int i=;i<m;i++)printf("%lld\n",ans[i]),ans[i+]+=ans[i]; //ans求出来的其实是每个操作引起的变化量
return ; //(它不是一直在*type么)
}
bzoj 3295 (洛谷3157、3193) [Cqoi2011]动态逆序对——树套树 / CDQ分治的更多相关文章
- 【洛谷3157】[CQOI2011] 动态逆序对(CDQ分治)
点此看题面 大致题意: 给你一个从\(1\)到\(n\)的排列,问你每次删去一个元素后剩余的逆序对个数. 关于\(80\)分的树套树 为了练树套树,我找到了这道题目. 但悲剧的是,我的 线段树套\(T ...
- BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那 ...
- bzoj3295 洛谷P3157、1393 动态逆序对——树套树
题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...
- [bzoj3295][Cqoi2011]动态逆序对_主席树
动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- 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 ...
- 洛谷 P3157 [CQOI2011]动态逆序对 解题报告
P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...
- bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对
http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...
随机推荐
- MySQL 触发器简单实例 - 转载
MySQL 触发器简单实例 触发器:可以更新,删除,插入触发器,不同种类的触发器可以存在于同一个表,但同种类的不能有多个.一个更新.一个删除是可以共存的. ~~语法~~ CREATE TRIGGER ...
- NumPy来自数值范围的数组
NumPy - 来自数值范围的数组 这一章中,我们会学到如何从数值范围创建数组. numpy.arange 这个函数返回ndarray对象,包含给定范围内的等间隔值. numpy.arange(sta ...
- scala学习手记21 - 传递变长参数
在Java中是可以使用变长参数的,如下面的方法: public void check(String ... args){ for(String tmp : args){ System.out.prin ...
- const对象 不能调用非const修饰的成员函数
class class UIRect:public RECT { public: UIRect(LONG leftT = 0, LONG topT = 0, LONG rightT = 0, LONG ...
- cassandra 之 集群部署
其实关于部署没啥好说的,修改config/cassandra.yaml以下几个地方就可以了 cluster_name: 'cluster_cassandra' data_file_directorie ...
- srm开发(基于ssh)(3)
联系人管理 (1)客户和联系人一对多配置(重点) (2)新增联系人 -新增功能实现 -Struts2实现文件上传 (3)联系人列表 -no session问题 (4)客户和联系人级联删除 联系人管理模 ...
- EF6 Code First 系列 (四):SQLite的DropCreateDatabaseIfModelChanges和乐观并发控制
没什么好说的,能支持DropCreateDatabaseIfModelChanges和RowVersion的Sqlite谁都想要.EntityFramework7正在添加对Sqlite的支持,虽然EF ...
- Ajax的跨域问题(包括解决方案)?
原因:js的同源策略限制,不同源会造成跨域 哪些情况会造成跨域? 子域名不同(WWW) 2.主域名不同(baidu.com) 3.端口号不同 4.IP地址和网址不同 解决方案: 使用jsonp技术,但 ...
- Updated: EBS 12.1 + Transportable Tablespaces with Incremental Backup Option
Database migration across platforms of different "endian" (byte ordering) formats using th ...
- 【spark】常用转换操作:sortByKey()和sortBy()
1.sortByKey() 功能: 返回一个根据键排序的RDD 示例 val list = List(("a",3),("b",2),("c" ...