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

 

posted @ 2019-07-31 21:14  nervending  阅读(432)  评论(0编辑  收藏  举报