自己的思路挺常见,正着扫,反着扫,用树状数组维护 del 值。
但是用两种不同写法的 CDQ 分治一个爆零,一个满分,有没有大佬佬能解答一下qwq。
(除了CDQ分治函数其他的都是一模一样的)
满分:
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int N=1e5+9;
int n;
int m;
int t[N];
struct node{
int val;
int del;
int ans;
} a[N];
int pos[N];
int origin;
int read()
{
int f=1,x=0;
char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^'0');s=getchar(); }
return f*x;
}
bool cmp1(node a,node b)
{
return a.val<b.val;
}
bool cmp2(node a,node b)
{
return a.del<b.del;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int val)
{
//cout<<"x= "<<x<<endl;
while(x<=n+1)
{
t[x]+=val;
x+=lowbit(x);
}
}
int query(int x)
{//
int ret=0;
while(x)
{
ret+=t[x];
x-=lowbit(x);
}
return ret;
}
void CDQ(int l,int r)
{
if(r-l==1) return;
int mid=(l+r)/2;
CDQ(l,mid);
CDQ(mid,r);
int i=l+1;
int j=mid+1;
for(;i<=mid;i++)
{
while(a[i].val>a[j].val&&j<=r)
{
add(a[j].del,1);
j++;
}
a[i].ans+=query(m+1)-query(a[i].del);
}
i=l+1;
j=mid+1;//回撤操作
for(;i<=mid;i++)
{
while(a[i].val>a[j].val&&j<=r)
{
add(a[j].del,-1);
j++;
}
}
i=mid;
j=r;
for(;j>mid;j--)
{
while(a[j].val<a[i].val&&i>l)
{
add(a[i].del,1);
i--;
}
a[j].ans+=query(m+1)-query(a[j].del);
}
i=mid;
j=r;
for(;j>mid;j--)
{
while(a[j].val<a[i].val&&i>l)
{
add(a[i].del,-1);
i--;
}
}
sort(a+l+1,a+r+1,cmp1);
}
signed main()
{
n=read();
m=read();
for(int i=1; i<=n; i++)
{
a[i].val=read();
pos[a[i].val]=i;
}
for(int i=1; i<=m; i++)
{
int p=read();
a[pos[p]].del=i;
}
for(int i=1; i<=n; i++)
if(a[i].del==0)
a[i].del=m+1;
for(int i=1; i<=n; i++)
{
origin+=query(n+1)-query(a[i].val);
add(a[i].val,1);
}
for(int i=1; i<=n; i++)
add(a[i].val,-1);
CDQ(0,n);
sort(a+1,a+n+1,cmp2);
for(int i=1; i<=m; i++)
{
printf("%lld\n",origin);
origin-=a[i].ans;
}
return 0;
}
0分:
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
#define mid ((l+r)>>1)
using namespace std;
const int N=1e5+9;
int n;
int m;
int t[N];
struct node{
int val;
int del;
int ans;
} a[N];
int pos[N];
int origin;
int read()
{
int f=1,x=0;
char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^'0');s=getchar(); }
return f*x;
}
bool cmp1(node a,node b)
{
return a.val<b.val;
}
bool cmp2(node a,node b)
{
return a.del<b.del;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int val)
{
//cout<<"x= "<<x<<endl;
while(x<=n+1)
{
t[x]+=val;
x+=lowbit(x);
}
}
int query(int x)
{//
int ret=0;
while(x)
{
ret+=t[x];
x-=lowbit(x);
}
return ret;
}
void CDQ(int l,int r)
{
if(l==r) return;
CDQ(l,mid);
CDQ(mid+1,r);
int i=l;
int j=mid+1;
for(;i<=mid;i++)
{
while(a[i].val>a[j].val&&j<=r)
{
add(a[j].del,1);
j++;
}
a[i].ans+=query(m+1)-query(a[i].del);
}
i=l;
j=mid+1;//回撤操作
for(;i<=mid;i++)
{
while(a[i].val>a[j].val&&j<=r)
{
add(a[j].del,-1);
j++;
}
}
i=mid;
j=r;
for(;j>mid;j--)
{
while(a[j].val<a[i].val&&i>l)
{
add(a[i].del,1);
i--;
}
a[j].ans+=query(m+1)-query(a[j].del);
}
i=mid;
j=r;
for(;j>mid;j--)
{
while(a[j].val<a[i].val&&i>l)
{
add(a[i].del,-1);
i--;
}
}
sort(a+l,a+r+1,cmp1);
}
signed main()
{
n=read();
m=read();
for(int i=1; i<=n; i++)
{
a[i].val=read();
pos[a[i].val]=i;
}
for(int i=1; i<=m; i++)
{
int p=read();
a[pos[p]].del=i;
}
for(int i=1; i<=n; i++)
if(a[i].del==0)
a[i].del=m+1;
for(int i=1; i<=n; i++)
{
origin+=query(n+1)-query(a[i].val);
add(a[i].val,1);
}
for(int i=1; i<=n; i++)
add(a[i].val,-1);
CDQ(1,n);
sort(a+1,a+n+1,cmp2);
for(int i=1; i<=m; i++)
{
printf("%lld\n",origin);
origin-=a[i].ans;
}
return 0;
}