• [noi1774]array


    容易想到树套树,但数据范围太大,会超时
    考虑平衡树的作用,就是将这个区间内的所有数排序,所以可以离线+归并来处理,预处理复杂度$o(nlog n)$,然后考虑维护:1.删除;2.询问
    删除操作维护可以使用并查集,可以通过$alpha(n)$的时间里快速找到每一个点的上和下元素
    询问操作可以二分查找,这样的复杂度为$o(qlog^{2} n+qlog ncdot alpha(n))$,考虑优化掉二分的复杂度:对于每一个数,合并时记录左右区间中比他小/大且最接近的数,这样只需要在最开始二分一次就可以传递下来,复杂度降为$o(qlog ncdot alpha(n))$
    实现中可能有一些细节问题:1.$nex[k].fi.fi$表示了左子树中小于等于它的最大数,若不存在则为最小的数,若没有数就随便(在query中要判断这个区间是否存在数,而且有可能因为删除而没有数),其余同理;2.每一个数要存储个数,否则会导致存在但无法找到;3.如果最小或最大的数删掉,并查集就指向不存在的位置来表示
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 1000005
      4 #define mid (l+r>>1)
      5 #define L (k<<1)
      6 #define R (L+1)
      7 #define mp make_pair
      8 #define fi first
      9 #define se second
     10 #define oo 0x3f3f3f3f
     11 struct ji{
     12     int p,l,r,k;
     13 }q[N];
     14 vector<int>f[N<<1],tot[N<<1],fa[2][N<<1];
     15 vector<pair<pair<int,int>,pair<int,int> > >nex[N<<1];
     16 int n,m,x,y,ans[N],sz[N<<1],now[N<<1];
     17 int find(int p,int x,int k){
     18     if ((k==sz[x])||(k==fa[p][x][k]))return k;
     19     return fa[p][x][k]=find(p,x,fa[p][x][k]); 
     20 }
     21 void add(int k,int l,int r,int x,int y){
     22     now[k]++;
     23     if (l==r){
     24         sz[k]=1;
     25         f[k].push_back(y);
     26         tot[k].push_back(1);
     27         return;
     28     }
     29     if (x<=mid)add(L,l,mid,x,y);
     30     else add(R,mid+1,r,x,y);
     31 }
     32 void merge(int k,int l,int r){
     33     if (l==r){
     34         if (!sz[k])return;
     35         fa[0][k].push_back(0);
     36         fa[1][k].push_back(0);
     37         return;
     38     }
     39     merge(L,l,mid);
     40     merge(R,mid+1,r);
     41     for(int i=0,j=0;(i<sz[L])||(j<sz[R]);){
     42         fa[0][k].push_back(sz[k]);
     43         fa[1][k].push_back(sz[k]++);
     44         if ((i<sz[L])&&(j<sz[R])&&(f[L][i]==f[R][j])){
     45             nex[k].push_back(mp(mp(i,i),mp(j,j)));
     46             f[k].push_back(f[L][i]);
     47             tot[k].push_back(tot[L][i++]+tot[R][j++]);
     48             continue;
     49         }
     50         if ((i<sz[L])&&((j==sz[R])||(f[L][i]<f[R][j]))){
     51             nex[k].push_back(mp(mp(i,i),mp(j-(j>0),j-((j>0)&&(j==sz[R])))));
     52             f[k].push_back(f[L][i]);
     53             tot[k].push_back(tot[L][i++]);
     54         }
     55         else{
     56             nex[k].push_back(mp(mp(i-(i>0),i-((i>0)&&(i==sz[L]))),mp(j,j)));
     57             f[k].push_back(f[R][j]);
     58             tot[k].push_back(tot[R][j++]);
     59         }
     60     }
     61 }
     62 void del(int k,int l,int r,int x,int y){
     63     now[k]--;
     64     if (--tot[k][y]==0){
     65         if (!y)fa[0][k][y]=sz[k];
     66         else fa[0][k][y]=fa[0][k][y-1];
     67         if (y==sz[k]-1)fa[1][k][y]=sz[k];
     68         else fa[1][k][y]=fa[1][k][y+1];
     69     }
     70     if (l==r)return;
     71     if (x<=mid)del(L,l,mid,x,nex[k][y].fi.fi);
     72     else del(R,mid+1,r,x,nex[k][y].se.fi);
     73 }
     74 int query(int k,int l,int r,int x,int y,int z,int a,int b){
     75     if ((l>y)||(x>r)||(!now[k]))return oo;
     76     if ((x<=l)&&(r<=y)){
     77         int ans=oo;
     78         if (find(0,k,a)<sz[k])ans=min(ans,abs(z-f[k][find(0,k,a)]));
     79         if (find(1,k,b)<sz[k])ans=min(ans,abs(z-f[k][find(1,k,b)]));
     80         return ans;
     81     }
     82     return min(query(L,l,mid,x,y,z,nex[k][a].fi.fi,nex[k][b].fi.se),query(R,mid+1,r,x,y,z,nex[k][a].se.fi,nex[k][b].se.se));
     83 }
     84 int main(){
     85     scanf("%d%d",&n,&m);
     86     for(int i=1;i<=m;i++){
     87         scanf("%d%d",&q[i].p,&q[i].l);
     88         if (q[i].p)scanf("%d%d",&q[i].r,&q[i].k);
     89         else{
     90             scanf("%d",&q[i].k);
     91             add(1,1,n,q[i].l,q[i].k);
     92         }
     93     }
     94     merge(1,1,n);
     95     for(int i=m;i;i--)
     96         if (!q[i].p)del(1,1,n,q[i].l,lower_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin());
     97         else{
     98             x=upper_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin()-1;
     99             y=lower_bound(f[1].begin(),f[1].end(),q[i].k)-f[1].begin();
    100             ans[++ans[0]]=query(1,1,n,q[i].l,q[i].r,q[i].k,max(x,0),y);
    101         }
    102     for(int i=ans[0];i;i--)
    103         if (ans[i]==oo)printf("-1
    ");
    104         else printf("%d
    ",ans[i]);
    105 } 
    View Code
  • 相关阅读:
    java开发——Cloneable接口、clone()方法和深浅拷贝
    intellij idea 显示Arraylist 扩容过程 解决not showing null elements
    ArrayList的扩容方式和扩容时机
    【laravel5.4】发送alisms短信和163邮箱
    【laravel5.4】重定向带参数
    【laravel5.4】vue分页删除
    【laravel5.4】Baum无限极分类和collect助手函数、transform()中间件(转换数据)方法使用
    【laravel5.4】使用baum ode 类库实现无限极分类
    【VUE+laravel5.4】vue给http请求 添加请求头数据
    【laravel5.4】关键字【use】使用
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13089482.html
Copyright © 2020-2023  润新知