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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

jzoj3854-分组【树状数组,线段树】

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

正題

題目鏈接:https://jzoj.net/senior/#contest/show/2990/2


題目大意

一個小隊滿足要求

  • 隊長的地位最高
  • 所有隊員和隊長的年齡差不超過kkk
  • 給出nnn個人的地位和年齡,qqq個詢問

    每次詢問一組(x,y)(x,y)(x,y)求若(x,y)(x,y)(x,y)在同一個隊里那這個隊的最多人數。


    解題思路

    我們將年齡離散化然后按照地位從大到小排序。

    然后我們用樹狀數組維護出每個人作為隊長時小隊的最多人數。

    之后我們對于每個詢問(x,y)(x,y)(x,y),默認yyy的地位大于xxx

    我們按照地位從大到小枚舉,對于每個(x,y)(x,y)(x,y),我們搞定滿足條件的年齡范圍(l,r)(l,r)(l,r),然后將地位比yyy大的最多人數都丟進線段樹里,然后查詢區間(l,r)(l,r)(l,r)即可。


    codecodecode

    #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=1e5+10; struct node{int r,w,num; }a[N]; int n,k,Q,cnt,ans[N]; int b[N],num[N],l[N],r[N],v[N]; vector<int> q[N]; struct Tree_Array{#define lowbit(x) (x&-x)int t[N];void Change(int x,int z){while(x<=n){t[x]+=z;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;}#undef lowbit(x) }TA; struct Seq_Tree{struct Tree_node{int l,r,w;}t[N*4];void Build(int x,int l,int r){t[x].l=l;t[x].r=r;t[x].w=-1;if(l==r)return;int mid=(l+r)/2;Build(x*2,l,mid);Build(x*2+1,mid+1,r);}void Change(int x,int pos,int z){if(t[x].l==t[x].r){t[x].w=max(t[x].w,z);return;}int mid=(t[x].l+t[x].r)>>1;if(pos<=mid) Change(x*2,pos,z);else Change(x*2+1,pos,z);t[x].w=max(t[x*2].w,t[x*2+1].w);}int Ask(int x,int l,int r){if(t[x].l==l&&t[x].r==r)return t[x].w;int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return Ask(x*2,l,r);if(l>mid) return Ask(x*2+1,l,r);return max(Ask(x*2,l,mid),Ask(x*2+1,mid+1,r));} }T; bool cmp(node x,node y) {return x.r>y.r;} int main() {scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)scanf("%d",&a[i].r),a[i].num=i;for(int i=1;i<=n;i++)scanf("%d",&a[i].w),b[++cnt]=a[i].w;sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){num[a[i].num]=i;l[i]=lower_bound(b+1,b+1+cnt,a[i].w-k)-b;r[i]=upper_bound(b+1,b+1+cnt,a[i].w+k)-b-1;a[i].w=lower_bound(b+1,b+1+cnt,a[i].w)-b;TA.Change(a[i].w,1);}scanf("%d",&Q);for(int i=1;i<=Q;i++){int x,y;scanf("%d%d",&x,&y);x=num[x];y=num[y];if(x<y)swap(x,y);q[y].push_back(i);v[i]=x;}int w=1;T.Build(1,1,cnt);for(int i=1;i<=n;i++){while(w<=n&&a[w].r>=a[i].r){int val=TA.Ask(r[w])-TA.Ask(l[w]-1);T.Change(1,a[w].w,val);w++;}for(int j=0;j<q[i].size();j++){int x=v[q[i][j]],y=i;int L=max(l[x],l[y]),R=min(r[x],r[y]);if(L>R) ans[q[i][j]]=-1;else ans[q[i][j]]=T.Ask(1,L,R);}TA.Change(a[i].w,-1);}for(int i=1;i<=Q;i++)printf("%d\n",ans[i]); }

    總結

    以上是生活随笔為你收集整理的jzoj3854-分组【树状数组,线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

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