[noi1774]array

容易想到树套树,但数据范围太大,会超时
考虑平衡树的作用,就是将这个区间内的所有数排序,所以可以离线+归并来处理,预处理复杂度$o(n\log n)$,然后考虑维护:1.删除;2.询问
删除操作维护可以使用并查集,可以通过$\alpha(n)$的时间里快速找到每一个点的上和下元素
询问操作可以二分查找,这样的复杂度为$o(q\log^{2} n+q\log n\cdot \alpha(n))$,考虑优化掉二分的复杂度:对于每一个数,合并时记录左右区间中比他小/大且最接近的数,这样只需要在最开始二分一次就可以传递下来,复杂度降为$o(q\log n\cdot \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\n");
104         else printf("%d\n",ans[i]);
105 } 
View Code

 

posted @ 2020-06-10 22:02  PYWBKTDA  阅读(99)  评论(0编辑  收藏  举报