luogu P5324 [BJOI2019]删数
傳送門
不如先考慮暴力,能刪的序列首先有\(1,2,3...n\),還有就是升序排序后從后往前放數(shù),第\(i\)位要么放\(i\),要么放\(i+1\)位置的數(shù),例如\(1,2,4,4,5,6,9,9,9\)
如果一個(gè)數(shù)\(i\)出現(xiàn)了若干次,假如是\(num_i\)次,我們發(fā)現(xiàn)是可以在\(i,i-1,i-2...i-num_i+1\)上放\(i\)的,這樣放完之后,如果有的位置沒有用到現(xiàn)有的數(shù)放上去,那么就要從沒用的數(shù)里改一個(gè)放過來,問題也就是用一堆數(shù),最多能放多少個(gè)位置.考慮從后往前放,然后如果一個(gè)位置有多個(gè)數(shù)就接著用這種數(shù)往后放.如果放到一個(gè)位置\(j\),\(j\)有若干個(gè),當(dāng)前的\(i\)也有若干個(gè),我們只能用一種放,那么顯然要用更多的那種放.最后沒放數(shù)的位置數(shù)就是答案.
為了方便,我們把放數(shù)看成區(qū)間覆蓋,即一個(gè)\(i\)可以覆蓋\([i-num_i+1,i]\)這段區(qū)間,我們?cè)俳o所有覆蓋區(qū)間加上\(1\),那就是求\([1,n]\)中\(0\)的個(gè)數(shù).注意到修改的\(+1/-1\)都是整體的,所以如果把所有數(shù)放在一根數(shù)軸上,那么初始要統(tǒng)計(jì)的區(qū)間為\([1,n]\),然后整體\(+1\)相當(dāng)于統(tǒng)計(jì)區(qū)間整體向左移\(1\),然后 以原統(tǒng)計(jì)區(qū)間右端點(diǎn) 為右端點(diǎn) 的對(duì)應(yīng)區(qū)間覆蓋的貢獻(xiàn)要減掉,因?yàn)槟莻€(gè)右端點(diǎn)的數(shù)超過統(tǒng)計(jì)范圍,不能放進(jìn)來;整體\(-1\)相當(dāng)于統(tǒng)計(jì)區(qū)間整體向右移\(1\),然后 以原統(tǒng)計(jì)區(qū)間右端點(diǎn) 為右端點(diǎn) 的對(duì)應(yīng)區(qū)間覆蓋的貢獻(xiàn)要加上;單點(diǎn)修改,也就是原來的\(num_{a_p}\)減\(1\),后面的新的\(num\)加\(1\),這導(dǎo)致對(duì)應(yīng)兩個(gè)覆蓋區(qū)間左端點(diǎn)右移和左移.這些東西可以用線段樹維護(hù),注意線段樹的葉子數(shù)量應(yīng)該是\(n+q+q\)
至于區(qū)間\(0\)的數(shù)量,用值域線段樹維護(hù)因?yàn)閰^(qū)間\(+1\),某個(gè)位置最少為\(0\),只要維護(hù)區(qū)間最小值及數(shù)量就行了
// luogu-judger-enable-o2 #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<vector> #include<cmath> #include<ctime> #include<queue> #include<map> #include<set> #define LL long long #define db doubleusing namespace std; const int N=150000+10,M=N*3; int rd() {int x=0,w=1;char ch=0;while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*w; } struct node {int mi,nm;node(){mi=0,nm=1;}node(int nmi,int nnm){mi=nmi,nm=nnm;}node operator + (const node &bb) const{if(mi==bb.mi) return node(mi,nm+bb.nm);return mi<bb.mi?(*this):bb;}void ad(int x){mi+=x;} }s[M<<2],nw; int tg[M<<2]; void psup(int o){s[o]=s[o<<1]+s[o<<1|1];} void psdn(int o){if(tg[o]) s[o<<1].ad(tg[o]),tg[o<<1]+=tg[o],s[o<<1|1].ad(tg[o]),tg[o<<1|1]+=tg[o],tg[o]=0;} #define mid ((l+r)>>1) int nl,nr; void modif(int o,int l,int r,int ll,int rr,int x) {if(ll<=l&&r<=rr){s[o].ad(x),tg[o]+=x;return;}psdn(o);if(ll<=mid) modif(o<<1,l,mid,ll,rr,x);if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr,x);psup(o); } void modif(int lx,int x) {int o=1,l=nl,r=nr,st[21],tp=0;while(l<r){st[++tp]=o,psdn(o);if(lx<=mid) o=o<<1,r=mid;else o=o<<1|1,l=mid+1;}s[o].ad(x);while(tp){o=st[tp--];psup(o);} } node quer(int o,int l,int r,int ll,int rr) {if(ll<=l&&r<=rr) return s[o];psdn(o);node an;an.mi=M;if(ll<=mid) an=an+quer(o<<1,l,mid,ll,rr);if(rr>mid) an=an+quer(o<<1|1,mid+1,r,ll,rr);psup(o);return an; } void bui(int o,int l,int r) {if(l==r) return;bui(o<<1,l,mid),bui(o<<1|1,mid+1,r);psup(o); } int n,q,a[N],nm[M],ll=150001,rr;int main() {n=rd(),q=rd();rr=ll+n-1;nl=ll-q,nr=rr+q;bui(1,nl,nr);for(int i=1;i<=n;++i){a[i]=rd()+ll-1;++nm[a[i]];modif(a[i]-nm[a[i]]+1,1);}while(q--){int p=rd();if(!p){if(~rd()){if(nm[rr]) modif(1,nl,nr,rr-nm[rr]+1,rr,-1);--ll,--rr;}else{++ll,++rr;if(nm[rr]) modif(1,nl,nr,rr-nm[rr]+1,rr,1);}}else{if(a[p]<=rr) modif(a[p]-nm[a[p]]+1,-1);--nm[a[p]];a[p]=rd()+ll-1;++nm[a[p]];modif(a[p]-nm[a[p]]+1,1);}nw=quer(1,nl,nr,ll,rr);printf("%d\n",nw.mi?0:nw.nm);}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/smyjr/p/10770696.html
總結(jié)
以上是生活随笔為你收集整理的luogu P5324 [BJOI2019]删数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 字符编码判断 charde
- 下一篇: jupyter nootbook本地使用