hdu6621 2019hdu多校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 segtree{public: #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; } } }