动态逆序对(删除数)--洛谷P1393(离散化+分块+树状数组)&洛谷P3157

题目链接https://www.luogu.org/problem/P1393

题目描述

对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i

输入格式

第一行,两个数n,m,表示序列中有n个数,要删去m个数

第二行n个数,表示给定的序列。

第三行m个数,第i个数di表示要删去原序列中的第di个数。

输出格式

一行m+1个数。第一个数表示给定序列的逆序对组数,第i+1个数表示删去第di个数后序列的逆序对组数(删去的数不再恢复)

输入输出样例

输入 

6 3
5 4 2 6 3 1
2 1 4

输出

11 7 4 2

说明/提示

对于20%的数据,n≤2500

对于另30%的数据,m=0

对于100%的数据,n≤40000,m≤n/2,且保证第二行n个数互不相同,第三行m个数互不相同。


这题题目有点问题,它的a[i]的范围没给你,导致了一发RE。。。所以我们需要对a[i]离散化,又由于他的a[i]是相互不同的,那么我们sort完之后用unordered_map离散化就好了:

for (int i=1; i<=n; i++) {
	in(a[i].val);//快读
	b[i]=a[i];
}
sort(b+1,b+1+n,cmp);
for (int i=1; i<=n; i++) q[b[i].val]=i;

接下来就是暴力分块了,首先我们要清楚的是,删去了这个数之后,他会的逆序对贡献会减少前面比他大的数的个数,再减少后面比他小的数的个数,比如5 4 3 2 1  我们删去了3,那么前面比他大的数的个数,也就是2(5和4比他大),后面比他小的数的个数为2(2和1)

所以我们就直接对每个块排序,对于包含位置x的块直接暴力数:

if (loca==i){
	for (int j=L[i]; j<=R[i]; j++) {
		if (a[j].pos==pos) {
			a[j].val=inf;
			continue;
		}
		if ((a[j].posval) || (a[j].pos>pos && a[j].val

对于loca前面的块,我们找有多少个比他大的数的个数,也就是二分查找:

if (i

后面的块也是一样的。

当然,我们对我们需要对块进行初始化,先排好序就好了

以下是AC代码:

#include 
using namespace std;

const int mac=1e5+10;
const int inf=1e9+10;

#define ll long long

int L[1000],R[1000],id[mac];
int tree[mac],mp[mac],t,n;
ll ans=0;
struct node
{
    int pos,val;
    bool operator<(const node &a)const{
        return valR[i]) continue;
        if (iloca){
            int it=lower_bound(a+L[i],a+R[i]+1,node{pos,val})-(a+L[i]);
            ans-=it;
        }
        else{
            for (int j=L[i]; j<=R[i]; j++){
                if (a[j].pos==pos){a[j].val=inf;continue;}
                if ((a[j].posval) || (a[j].pos>pos && a[j].val'9' || ch<'0') ch=getchar();
	while (ch<='9' && ch>='0') f=(f<<3)+(f<<1)+ch-'0',ch=getchar();
	x=f;
}

void out(ll x)
{
	if (x>=10)
		out(x/10);
	putchar(x%10+'0');
}

unordered_mapq;

int main()
{
    //freopen("in.txt","r",stdin);
	int m;
    in(n);in(m);
    t=sqrt(n);
    for (int i=1; i<=t; i++){
        L[i]=(i-1)*t+1;
        R[i]=i*t;
    }
    if (R[t]

还有一题类似的,洛谷P3157,这题的数据比较毒瘤,要开O2优化(可以手动开O2)才能过

题目链接https://www.luogu.org/problem/P3157

方法和上面是一样的,删去离散化就可以了:

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include 
using namespace std;

const int mac=1e5+10;
const int inf=1e9+10;

#define ll long long

int L[1000],R[1000],id[mac];
int tree[mac],mp[mac],t,n;
ll ans=0;
struct node
{
    int pos,val;
    bool operator<(const node &a)const{
        return valR[i]) continue;
        if (iloca){
            int it=lower_bound(a+L[i],a+R[i]+1,node{pos,val})-(a+L[i]);
            ans-=it;
        }
        else{
            for (int j=L[i]; j<=R[i]; j++){
                if (a[j].pos==pos){a[j].val=inf;continue;}
                if ((a[j].posval) || (a[j].pos>pos && a[j].val'9' || ch<'0') ch=getchar();
	while (ch<='9' && ch>='0') f=(f<<3)+(f<<1)+ch-'0',ch=getchar();
	x=f;
}

void out(ll x)
{
	if (x>=10)
		out(x/10);
	putchar(x%10+'0');
}

int main()
{
    //freopen("in.txt","r",stdin);
	int m;
    in(n);in(m);
    t=sqrt(n);
    for (int i=1; i<=t; i++){
        L[i]=(i-1)*t+1;
        R[i]=i*t;
    }
    if (R[t]

 

你可能感兴趣的:(#,分块,#,线段树&树状数组)