前言
容易写挂(对于新手与蒟蒻)
题面
洛谷;
sol
CDQ
如果按照三维偏序那样求,那么会漏掉一些情况。所以要跑两遍cdq。
两遍CDQ又会有一个问题,就是判等于的问题。第一遍CDQ第三维判等于,第二遍判不等于.
code
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int lowbit(int k){return (-k)&k;}
namespace zjy_io{
inline char gc(){
static char buf[1<<6],*p1=buf,*p2=buf;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<6,stdin),p1==p2)?EOF:*p1++;
}
template <class T>
inline void read(T&data){
data=0;
register char ch=0;
register int caa=1;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=gc();
ch=='-'?caa=-1,ch=gc():caa=1;
while(ch<='9'&&ch>='0'){
data=(data<<3)+(data<<1)+(ch^48);
ch=gc();
}
data*=caa;
}
inline char Getchar(){
register char ch=0;
while(ch<'A'||ch>'Z')ch=gc();return ch;
}
inline void write(LL x){
if(x>9)write(x/10);
putchar(x%10+'0');
}
}
using namespace zjy_io;
const int _ = 1.03e5;
int n,m,cnt;
struct node{
int a,b,c;
}s[_],q[_];
int num[_];//ai<aj,bi>bj,ci<cj,
LL ans[_];
LL tree[_];
struct er{
int a,b;
}rr[_];
inline void modify(register int loc,register int zh){
for(register int i=loc;i<=n;i+=lowbit(i))tree[i]+=zh;
}
inline int query(register int loc){
register int ret1=0,ret2=0;
for(register int i=loc-1;i;i-=lowbit(i))ret1+=tree[i];
for(register int i=n;i;i-=lowbit(i))ret2+=tree[i];
return ret2-ret1;
}
bool cmp(node x,node y){
return x.a<y.a;
}
void CDQ1(register int L,register int R){
if(L==R)return;
register int mid=(L+R)>>1;
CDQ1(L,mid);CDQ1(mid+1,R);
register int pin1=mid,pin2=R,ppl=R;
for(;pin2>=mid+1;pin2--){
while(s[pin1].b>s[pin2].b&&pin1>=L){
q[ppl]=s[pin1];
rr[++cnt]=(er){s[pin1].c,1};
modify(s[pin1].c,1);--ppl,--pin1;
}
ans[s[pin2].c]+=query(s[pin2].c+1);
//cout<<L<<' '<<R<<' '<<s[pin2].a<<' '<<ans[s[pin2].c]<<endl;
q[ppl]=s[pin2];ppl--;
}
while(pin1>=L){q[ppl]=s[pin1];--ppl,--pin1;}
for(register int i=L;i<=R;++i)s[i]=q[i];
for(register int i=1;i<=cnt;++i)modify(rr[i].a,-rr[i].b);cnt=0;
}
void CDQ(register int L,register int R){
if(L==R)return;
register int mid=(L+R)>>1;
CDQ(L,mid),CDQ(mid+1,R);
register int pin1=L,pin2=mid+1,ppl=L;
for(;pin1<=mid;pin1++){
while(s[pin1].b>s[pin2].b&&pin2<=R){
q[ppl]=s[pin2];
rr[++cnt]=(er){s[pin2].c,1};
modify(s[pin2].c,1),++ppl,++pin2;
}
ans[s[pin1].c]+=query(s[pin1].c),q[ppl]=s[pin1],ppl++;
}
while(pin2<=R)q[ppl]=s[pin2],++ppl,++pin2;
for(register int i=L;i<=R;++i)s[i]=q[i];
for(register int i=1;i<=cnt;++i)modify(rr[i].a,-rr[i].b);cnt=0;
}
int main(){
read(n),read(m);
for(register int i=1;i<=n;++i)
read(s[i].a),s[i].b=i,num[s[i].a]=i;
register int h;
for(register int i=1;i<=m;++i)
read(h),s[num[h]].c=i;
for(register int i=1;i<=n;++i)
if(!s[i].c)s[i].c=m+1;
sort(s+1,s+n+1,cmp);
CDQ(1,n);
sort(s+1,s+n+1,cmp);
for(register int i=m+1;i>=1;--i)
ans[i]=ans[i]+ans[i+1];
for(register int i=1;i<=m;++i)
write(ans[i]),puts("");
}