zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    克如斯卡尔 P1546
    真正的spfa
    第四课 最小生成树 要点
    关于vscode中nullptr未定义
    cmake学习笔记
    python学习笔记
    (BFS 图的遍历) 2906. kotori和迷宫
    (图论基础题) leetcode 997. Find the Town Judge
    (BFS DFS 并查集) leetcode 547. Friend Circles
    (BFS DFS 图的遍历) leetcode 841. Keys and Rooms
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13089482.html
Copyright © 2011-2022 走看看