【BZOJ4408】[FJOI2016]神秘數(主席樹)
阿新 • • 發佈:2019-03-07
直接 當前 def 依次 != tps ++i lin inline ,意味著\(x\)至少要翻一倍。
因此最多執行\(log\)次翻倍的操作。
抄起主席樹暴力維護就好了。
【BZOJ4408】[FJOI2016]神秘數(主席樹)
題面
BZOJ
洛谷
題解
考慮只有一次詢問。
我們把所有數排個序,假設當前可以表示出的最大數是\(x\)。
起始\(x=0\)。
依次考慮接下來的每個數\(a_i\),如果\(a_i\le x\),那麽沒有啥問題,\(x+=a_i\)。
如果\(a_i=x+1\),那麽也沒有問題,\(x+=a_i\)。
如果\(a_i>x\),那麽\(x+1\)就拼不出來了。
那麽顯然考慮每次詢問,首先把所有\(\le x\)的數全部加進來,然後考慮下一個比\(x\)大的數,如果其大於\(x+1\),那麽直接就\(GG\)了。
否則等於\(x+1\)
因此最多執行\(log\)次翻倍的操作。
抄起主席樹暴力維護就好了。
#include<iostream> #include<cstdio> using namespace std; #define MAX 100100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Node{int ls,rs,v;}t[MAX*35];int tot; void Modify(int &x,int l,int r,int p) { t[++tot]=t[x];x=tot;t[x].v+=p; if(l==r)return;int mid=(l+r)>>1; if(p<=mid)Modify(t[x].ls,l,mid,p); else Modify(t[x].rs,mid+1,r,p); } int Query(int x,int y,int l,int r,int p) { if(l==r)return t[x].v-t[y].v;int mid=(l+r)>>1; if(p<=mid)return Query(t[x].ls,t[y].ls,l,mid,p); else return Query(t[x].rs,t[y].rs,mid+1,r,p)+t[t[x].ls].v-t[t[y].ls].v; } int n,m,a[MAX],rt[MAX]; int main() { n=read(); for(int i=1;i<=n;++i)a[i]=read(); for(int i=1;i<=n;++i)Modify(rt[i]=rt[i-1],1,1e9,a[i]); m=read(); while(m--) { int l=read(),r=read(),x=0; while(x<1e9) { int v=Query(rt[r],rt[l-1],1,1e9,x+1); if(v==x)break;x=v; } printf("%d\n",x+1); } return 0; }
【BZOJ4408】[FJOI2016]神秘數(主席樹)