日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P4587-[FJOI2016]神秘数【主席树】

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4587-[FJOI2016]神秘数【主席树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P4587


題目大意

nnn個數,每次選擇一個區間,然后詢問這個區間的子集和所不能表示的最小的正整數。


解題思路

假設我們從小到大加入數字,我們發現如果這個數不是111顯然這個區間內至少有一個111

我們假設現在能表示的最小的數是mxmxmx,加入一個數xxx時,如果x>mx+1x> mx+1x>mx+1那么mx+1mx+1mx+1就不能表現出來,否則我們就可以表示出1~mx+x1\sim mx+x1mx+x的數,即讓mx=mx+xmx=mx+xmx=mx+x

考慮如何優化,如果我們之前能表現出1~mx1\sim mx1mx,加上某些數之后能表現出1~mx′1\sim mx'1mx了,那么我們顯然可以尋找任何一個在mx+1~mx′+1mx+1\sim mx'+1mx+1mx+1里的數字來擴充,那么我們之間將這段區間的和取來不就好了嗎。這個可以用主席樹維護。

時間復雜度如何,我們發現每次找到的區間和如果還能往下顯然是大于mxmxmx的,然后會讓mx′+mxmx'+mxmx+mx也就是每次至少可以讓mx′mx'mx加上自己的一半,這個時間復雜度是接近倍增也就是logloglog的。

所以時間復雜度O(nlog?2n)O(n\log^2 n)O(nlog2n)


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=1e6+10,M=5e6+10,inf=1e9; ll n,m,cnt,rt[N]; ll ls[M],rs[M],sum[M]; ll Change(ll x,ll L,ll R,ll val){ll y=++cnt;rs[y]=rs[x];ls[y]=ls[x];ll mid=(L+R)>>1;sum[y]=sum[x]+val;if(L==R)return y;if(val<=mid)ls[y]=Change(ls[x],L,mid,val);else if(val>mid)rs[y]=Change(rs[x],mid+1,R,val);return y; } ll Ask(ll x,ll y,ll L,ll R,ll l,ll r){if(!(sum[x]-sum[y]))return 0;if(l==L&&r==R)return sum[x]-sum[y];ll mid=(L+R)>>1;if(r<=mid)return Ask(ls[x],ls[y],L,mid,l,r);if(l>mid)return Ask(rs[x],rs[y],mid+1,R,l,r);return Ask(ls[x],ls[y],L,mid,l,mid)+Ask(rs[x],rs[y],mid+1,R,mid+1,r); } int main() {scanf("%lld",&n);for(ll i=1;i<=n;i++){ll x;scanf("%lld",&x);rt[i]=Change(rt[i-1],1,inf,x);}scanf("%lld",&m);for(ll i=1;i<=m;i++){ll l,r,lim=0,at=0;scanf("%lld%lld",&l,&r);while(1){ll w=Ask(rt[r],rt[l-1],1,inf,lim+1,at+1);if(!w)break;lim=at+1;at+=w;}printf("%lld\n",at+1);}return 0; }

總結

以上是生活随笔為你收集整理的P4587-[FJOI2016]神秘数【主席树】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。