hdu66212019hdu多校4 线段树上乱搞
Posted nervendnig
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu66212019hdu多校4 线段树上乱搞相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?pid=6621
每个点维护该点内元素排序后的结果,每次寻味取出所有可能有解的区间
对每个区间二分,得到一个ub,一个lb,然后双向遍历每个指针k轮,每次取出最小的值,然后移动一次指针
第k轮得到的即为答案
复杂度$O(nlogn(k+logn))$,后面的第二个logn很难跑满,而k又很大,所以最终复杂度大概是$O(knlogn)$
#include<bits/stdc++.h> #define endl ‘\n‘ #define all(x) x.begin(),x.end() #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #pragma GCC optimize("Ofast") const int maxn=1e5+8; using namespace std; int casn,n,m,k,a[maxn]; class segtreepublic: #define nd node[now] #define ndl node[now<<1] #define ndr node[now<<1|1] struct segnode int l,r,len; vector<int> arr; node[maxn<<2|3]; void pushup(int now) nd.arr.clear(); for(auto i:ndl.arr) nd.arr.push_back(i); for(auto i:ndr.arr) nd.arr.push_back(i); sort(all(nd.arr)); void maketree(int s,int t,int now=1) nd.l=s,nd.r=t,nd.len=t-s+1; if(s==t) nd.arr.clear(); nd.arr.push_back(a[s]); return ; maketree(s,(s+t)>>1,now<<1); maketree((s+t)/2+1,t,now<<1|1); pushup(now); vector<int> fd1,fd2; void query(int s,int t,int q,int now=1) if(s<=nd.l&&t>=nd.r) if(nd.arr.back()>q) fd1.push_back(now); if(nd.arr[0]<=q) fd2.push_back(now); return ; if(s<=ndl.r) query(s,t,q,now<<1); if(t>ndl.r) query(s,t,q,now<<1|1); int solve(int q,int k) int la=fd1.size(),lb=fd2.size(); vector<int> p1,p2; rep(i,0,la-1) int now=fd1[i]; int pos=upper_bound(all(nd.arr),q)-nd.arr.begin(); p1.push_back(pos); rep(i,0,lb-1) int now=fd2[i]; int pos=lower_bound(all(nd.arr),q)-nd.arr.begin(); if(pos==nd.len||nd.arr[pos]>q) pos--; p2.push_back(pos); int ans,id,flag; rep(i,0,k-1) ans=1e9,id=0,flag=0; rep(j,0,la-1) int p=p1[j],now=fd1[j]; if(now==-1) continue; if(nd.arr[p]-q<ans) ans=nd.arr[p]-q,id=j,flag=0; rep(j,0,lb-1) int p=p2[j],now=fd2[j]; if(now==-1) continue; if(q-nd.arr[p]<ans) ans=q-nd.arr[p],id=j,flag=1; if(flag==0) p1[id]++; if(p1[id]==node[fd1[id]].len) fd1[id]=-1; else p2[id]--; if(p2[id]==-1) fd2[id]=-1; return ans; tree; int main() IO; cin>>casn; while(casn--) cin>>n>>m; rep(i,1,n) cin>>a[i]; tree.maketree(1,n); int ans=0; while(m--) int l,r,a,k;cin>>l>>r>>a>>k; l^=ans,r^=ans,a^=ans,k^=ans; if(l>r) swap(l,r); tree.fd1.clear();tree.fd2.clear(); tree.query(l,r,a); ans=tree.solve(a,k); cout<<ans<<endl;
以上是关于hdu66212019hdu多校4 线段树上乱搞的主要内容,如果未能解决你的问题,请参考以下文章
2021HDU多校第三场 1009 Rise in Price 思维+乱搞
[hdu-6621]K-th Closest Distance 主席树 线段树 2019 多校4
HDU多校4 - 6992 Lawn of the Dead(线段树+模拟)