19-11-04-?
完了,壹佰场了……我估计我连壹万分都没有……$\text{QwQ}$
总结:
考场上全是暴力。
鬼知道分是哪里来的。
没挂分就是了。
22
|
Miemeng | 55
00:00:51
|
60
00:00:45
|
40
00:00:40
|
155
00:00:51
|
还应该再努力些……
解:
T2:
一棵神奇的线段树。
虽然暴力加剪枝可过,但是正解跑飞快。
首先观察神奇的操作,发现就是把一个点所控制子序列中所有的逆序对删掉。
那么每个点作为子序列中的点只能被删一次。
于是用线段树加速这个删的过程,保证了复杂度$\Theta(N \log N)$。
有点像小清新
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #define N 222222 #define LL long long #define lc(k) (k<<1) #define rc(k) (k<<1|1) using namespace std; int pn,qn; int arr[N]; LL dp[N],ans=0; vector<LL>ansv; namespace szsz{ int maxr=200010; LL pre[N]; inline int lowbit(int x){ return x&(-x); } void add(int pos,int v){ while(pos<=maxr){ pre[pos]+=v; pos+=lowbit(pos); } } LL query(int pos){ LL res=0; while(pos){ res+=pre[pos]; pos-=lowbit(pos); } return res; } } struct XDS{ int l,r; int val; LL dat; }rt[N<<2]; void build(int k,int l,int r){ rt[k].l=l,rt[k].r=r; if(l==r){ rt[k].dat=dp[l]; rt[k].val=arr[l]; return ; } int mid=(l+r)/2; build(lc(k),l ,mid); build(rc(k),mid+1,r ); rt[k].val=min(rt[lc(k)].val,rt[rc(k)].val); } LL spchange(int k,int l,int r,int va){ // cout<<k<<" "<<rt[k].l<<" "<<rt[k].r<<" "<<va<<" "<<rt[k].val<<endl; LL anss=0; if(rt[k].val>va) return 0; if(rt[k].l==rt[k].r){ LL va=rt[k].dat; rt[k].val=0x7fffffff; return va; } int mid=(rt[k].l+rt[k].r)/2; if(mid >= l) anss+=spchange(lc(k),l,r,va); if(mid < r) anss+=spchange(rc(k),l,r,va); rt[k].val=min(rt[lc(k)].val,rt[rc(k)].val); return anss; } int main(){ #ifndef LOCAL freopen("count.in" ,"r",stdin); freopen("count.out","w",stdout); #endif int a; ios_base::sync_with_stdio(false); cin>>pn>>qn; for(int i=1;i<=pn;i++) cin>>arr[i]; for(int i=pn;i>=1;i--){ dp[i]=szsz::query(arr[i]-1); ans+=dp[i]; szsz::add(arr[i],1); } ansv.push_back(ans); build(1,1,pn); for(int i=1;i<=qn;i++){ // cout<<"-------------"<<endl; cin>>a; ans-=spchange(1,a,pn,arr[a]); // cout<<"-------------"<<endl; ansv.push_back(ans); } for(int i=0;i<ansv.size();i++){ cout<<ansv[i]<<" "; } cout<<endl; }
Miemeng真的蒻