题目: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分治的更多相关文章

  1. 【洛谷3157】[CQOI2011] 动态逆序对(CDQ分治)

    点此看题面 大致题意: 给你一个从\(1\)到\(n\)的排列,问你每次删去一个元素后剩余的逆序对个数. 关于\(80\)分的树套树 为了练树套树,我找到了这道题目. 但悲剧的是,我的 线段树套\(T ...

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

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

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

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

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

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

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

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

  6. BZOJ 3295: [Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3865  Solved: 1298[Submit][Sta ...

  7. Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2886  Solved: 924[Submit][Stat ...

  8. 洛谷 P3157 [CQOI2011]动态逆序对 解题报告

    P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...

  9. bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...

随机推荐

  1. EF Code-First 学习之旅 多对多的关系

    public class Student { public Student() { this.Courses = new HashSet<Course>(); } public int S ...

  2. 一次穿墙渗透测试,利用IPC跨域

    Shell是怎么拿下的我们就不纠结了. 我们来上传菜刀一句话,来仔细分析分析. 先来看看内网环境把. 很高兴的是现在管理员在线.可以抓去文明密码. 但是很悲催的又是.服务器不支持走TCP协议.HTTP ...

  3. plot 含缺失值的图

    x = np.linspace(1,10,25) y = (x-4)**2 index = random.sample(range(25),5) # 从1-24中不放回随机抽取5个数 y[index ...

  4. NumPy来自数值范围的数组

    NumPy - 来自数值范围的数组 这一章中,我们会学到如何从数值范围创建数组. numpy.arange 这个函数返回ndarray对象,包含给定范围内的等间隔值. numpy.arange(sta ...

  5. NFS的安装配置使用

    /////////////////////////////NFS///////////////////////////////////////////////////写在前面:NFS在数据传输/信息传 ...

  6. LeetCode第[1]题(Java):Two Sum (俩数和为目标数的下标)——EASY

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  7. Appium 自动化测试(5)-- Appium详细介绍:Appium 手机自动化测试_TesterHome公开版pdf

  8. hdu4348区间更新的主席树+标记永久化

    http://acm.hdu.edu.cn/showproblem.php?pid=4348 sb的标记永久化即可,刚开始add和sum没复制过来wa了两发...,操作和原来的都一样,出来单点变成区间 ...

  9. OpenCV人脸检测并把图片写成avi视频

    读出某一个文件夹下“jpg”后缀的全部图片后,用的OpenCV自带的人脸检测检测图片中的人脸,调整图片的大小写成一个avi视频. 主要是要记录一下CvVideoWriter的用法和如何从文件夹中读取某 ...

  10. 移动国家号(MCC)

    定义移动国家号 Mobile Country Code (MCC)由三位十进制数组成,它表明移动用户(或系统)归属的国家. 格式移动国家号(MCC)由三个十进制数组成,编码范围为十进制的000-999 ...