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;
}
}
}

浙公网安备 33010602011771号