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

      歡迎訪問 生活随笔!

      生活随笔

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

      编程问答

      BZOJ3110: [Zjoi2013]K大数查询

      發布時間:2025/3/21 编程问答 29 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 BZOJ3110: [Zjoi2013]K大数查询 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

      BZOJ3110: [Zjoi2013]K大數查詢

      Description

      有N個位置,M個操作。

      操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入一個數c
      如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第C大的數是多少。

      Input

      第一行N,M
      接下來M行,每行形如1 a b c或2 a b c

      Output

      輸出每個詢問的結果

      Sample Input

      2 5
      1 1 2 1
      1 1 2 2
      2 1 1 2
      2 1 1 1
      2 1 2 3

      Sample Output

      1
      2
      1

      HINT

      【樣例說明】

      第一個操作 后位置 1 的數只有 1 , 位置 2 的數也只有 1 。

      第二個操作 后位置 1的數有 1 、 2 ,位置 2 的數也有 1 、 2 。

      第三次詢問 位置 1 到位置 1 第 2 大的數 是1 。

      第四次詢問 位置 1 到位置 1 第 1 大的數是 2 。

      第五次詢問 位置 1 到位置 2 第 3大的數是 1 。?

      N,M<=50000,N,M<=50000

      a<=b<=N

      1操作中abs(c)<=N

      2操作中c<=long long

      題解Here!

      剛學的樹套樹,就遇上了這題。

      然后我不知死活地一發線段樹Splay,完美地TLE了。。。

      附上炒雞長的代碼紀念:

      #include<iostream> #include<algorithm> #include<cstdio> #define MAXN 20000010 #define MAXM 50010 using namespace std; const long long maxn=50000; int n,m; namespace BST{int size=1,root[MAXM<<2];struct Splay{int son[2];int f,v,s,flag;}a[MAXN];inline void clean(int rt){a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].s=a[rt].v=a[rt].flag=0;}inline void pushup(int rt){if(!rt)return;a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+a[rt].flag;}inline void turn(int rt,int k){int x=a[rt].f,y=a[x].f;a[x].son[k^1]=a[rt].son[k];if(a[rt].son[k])a[a[rt].son[k]].f=x;a[rt].f=y;if(y)a[y].son[a[y].son[1]==x]=rt;a[x].f=rt;a[rt].son[k]=x;pushup(x);pushup(rt);}void splay(int rt,int ancestry,int i){while(a[rt].f!=ancestry){int x=a[rt].f,y=a[x].f;if(y==ancestry)turn(rt,a[x].son[0]==rt);else{int k=a[y].son[0]==x?1:0;if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);}else{turn(x,k);turn(rt,k);}}}if(ancestry==0)root[i]=rt;}void insert(int i,int x,int t){int rt=root[i];if(!rt){root[i]=rt=size++;a[rt].son[0]=a[rt].son[1]=a[rt].f=0;a[rt].v=x;a[rt].s=a[rt].flag=t;return;}int fa=0;while(1){if(a[rt].v==x){a[rt].flag+=t;pushup(rt);pushup(fa);break;}fa=rt;rt=a[rt].son[a[rt].v<x];if(!rt){rt=size++;a[rt].v=x;a[rt].flag=a[rt].s=t;a[rt].f=fa;a[fa].son[a[fa].v<x]=rt;a[rt].son[0]=a[rt].son[1]=0;pushup(fa);break;}}splay(rt,0,i);}int rank(int i,int x){int rt=root[i],s=0;while(rt){if(a[rt].v==x)return s+a[a[rt].son[0]].s;else if(a[rt].v<x){s+=a[a[rt].son[0]].s+a[rt].flag;rt=a[rt].son[1];}else rt=a[rt].son[0];}return s;}long long get_size(int i){int rt=root[i];return (long long)a[rt].s;} } namespace ST{#define LSON rt<<1#define RSON rt<<1|1#define LSIDE(x) a[x].l#define RSIDE(x) a[x].rstruct Segment_Tree{int l,r;}a[MAXM<<2];void buildtree(int l,int r,int rt){int mid;LSIDE(rt)=l;RSIDE(rt)=r;if(l==r)return;mid=l+r>>1;buildtree(l,mid,LSON);buildtree(mid+1,r,RSON);}void insert(int l,int r,int c,int rt){int mid;BST::insert(rt,c,min(RSIDE(rt),r)-max(LSIDE(rt),l)+1);if(LSIDE(rt)==RSIDE(rt))return;mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)insert(l,r,c,LSON);if(mid<r)insert(l,r,c,RSON);}int query_rank(int l,int r,int c,int rt){int mid,ans=0;if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return BST::rank(rt,c);mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)ans+=query_rank(l,r,c,LSON);if(mid<r)ans+=query_rank(l,r,c,RSON);return ans;}long long query_size(int l,int r,int rt){int mid,ans=0;if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return BST::get_size(rt);mid=LSIDE(rt)+RSIDE(rt)>>1;if(l<=mid)ans+=query_size(l,r,LSON);if(mid<r)ans+=query_size(l,r,RSON);return ans;}int get_kth(int l,int r,int k){int left=-maxn-1,right=maxn+1,mid,s;while(left<=right){mid=left+right>>1;s=query_rank(l,r,mid,1);if(s<k)left=mid+1;else right=mid-1;}return left-1;} } inline long long read(){long long date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w; } void work(){int f,x,y;long long k;while(m--){f=read();x=read();y=read();k=read();if(f==1)ST::insert(x,y,k,1);if(f==2){k=ST::query_size(x,y,1)-k+1;printf("%d\n",ST::get_kth(x,y,k));}} } void init(){n=read();m=read();ST::buildtree(1,n,1); } int main(){init();work();return 0; }

      正解也是樹套樹,然而是權值線段樹套動態開點區間線段樹。。。

      (蒟蒻表示并不會整體二分/cdq分治。。。藥丸。。。)

      外層是權值線段樹,實質上就是一個二分答案的過程。

      然后運用類似歸并樹和主席樹的思想,我們設詢問區間為?[ql,qr]?,答案區間為?[l,r]?,取其?midmid?,然后計算在左兒子?[l,mid]?和詢問區間?[ql,qr]?中的數的個數。

      那么我們就可以判斷答案是大于?mid?還是小于?mid?的了。

      而在權值線段樹的每一個節點上都建一個區間線段樹,來維護該權值在?[1,n]?所有區間上的出現次數,然后維護一個區間和就好了。

      記得離散化。

      附代碼:

      #include<iostream> #include<algorithm> #include<cstdio> #define MAXN 20000010 #define MAXM 50010 using namespace std; int n,m,K; int root[MAXM<<2],b[MAXM]; struct Question{int f,l,r;long long k; }que[MAXM]; namespace CT{long long size=0;struct Chairman_Tree{int l,r;long long sum,size;}a[MAXN];void insert(int left,int right,int l,int r,int &rt){if(!rt)rt=++size;a[rt].sum+=min(right,r)-max(left,l)+1;if(left<=l&&r<=right){a[rt].size++;return;}int mid=l+r>>1;if(left<=mid)insert(left,right,l,mid,a[rt].l);if(mid<right)insert(left,right,mid+1,r,a[rt].r);}long long query(int left,int right,int l,int r,int rt){if(!rt)return 0;if(left<=l&&r<=right)return a[rt].sum;int mid=l+r>>1;long long ans=a[rt].size*(min(right,r)-max(left,l)+1);if(left<=mid)ans+=query(left,right,l,mid,a[rt].l);if(mid<right)ans+=query(left,right,mid+1,r,a[rt].r);return ans;} } namespace ST{#define LSON rt<<1#define RSON rt<<1|1#define LSIDE(x) a[x].l#define RSIDE(x) a[x].rstruct Segment_Tree{int l,r;}a[MAXM<<2];void buildtree(int l,int r,int rt){int mid;LSIDE(rt)=l;RSIDE(rt)=r;if(l==r)return;mid=l+r>>1;buildtree(l,mid,LSON);buildtree(mid+1,r,RSON);}void update(int l,int r,int c,int rt){int mid;CT::insert(l,r,1,n,root[rt]);if(LSIDE(rt)==RSIDE(rt))return;mid=LSIDE(rt)+RSIDE(rt)>>1;if(c<=mid)update(l,r,c,LSON);else update(l,r,c,RSON);}long long query(int l,int r,long long c,int rt){if(LSIDE(rt)==RSIDE(rt))return LSIDE(rt);int mid=LSIDE(rt)+RSIDE(rt)>>1;long long t=CT::query(l,r,1,n,root[LSON]);if(c<=t)return query(l,r,c,LSON);else return query(l,r,c-t,RSON);} } inline long long read(){long long date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w; } void work(){int f,x,y;long long k;for(int cases=1;cases<=m;cases++){f=que[cases].f;x=que[cases].l;y=que[cases].r;k=que[cases].k;if(f==1)ST::update(x,y,K-k+1,1);if(f==2)printf("%d\n",b[K-ST::query(x,y,k,1)+1]);} } void init(){n=read();m=read();for(int i=1;i<=m;i++){que[i].f=read();que[i].l=read();que[i].r=read();que[i].k=read();if(que[i].f==1)b[++K]=que[i].k;}sort(b+1,b+K+1);K=unique(b+1,b+K+1)-b-1;for(int i=1;i<=m;i++)if(que[i].f==1)que[i].k=lower_bound(b+1,b+K+1,que[i].k)-b;ST::buildtree(1,K,1); } int main(){init();work();return 0; }

      ?

      轉載于:https://www.cnblogs.com/Yangrui-Blog/p/9315174.html

      總結

      以上是生活随笔為你收集整理的BZOJ3110: [Zjoi2013]K大数查询的全部內容,希望文章能夠幫你解決所遇到的問題。

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