看到题目感觉有点坏...
区间第k大,插入某个数...看起来怎么那么像主席树...、
tmd我不会
然后看看分类....堆?花了30min乱打一波优先队列...突然想起来stl不能直接输出q[k]。。。
然后转换思路...嗯,从树的角度出发...突然想起某道题...戳我
这样就变成了模板提...不过对模板不熟...调了3h+才发现有个小错误>_<(蒟蒻就要多刷题...)
于是就变成了一道送温暖提(Tjm:打波splay暖暖手)
题目链接:http://codevs.cn/problem/2573/
代码:
#include<bits/stdc++.h> #define ll long long #define maxn 60010 using namespace std; int num[maxn],son[maxn][3],f[maxn],value[2000000],data[maxn]; int root,tot,n,m,a[maxn]; void rotate(int x,int w){ int y=f[x]; num[y]=num[y]-num[x]+num[son[x][w]]; num[x]=num[x]-num[son[x][w]]+num[y]; son[y][3-w]=son[x][w]; if(son[x][w]) f[son[x][w]]=y; f[x]=f[y]; if(f[y]){ if(son[f[y]][1]==y) son[f[y]][1]=x; else son[f[y]][2]=x; } f[y]=x;son[x][w]=y; } void splay(int x){ while(f[x]!=0){ int y=f[x]; if(f[y]==0){ if(son[y][1]==x) rotate(x,2); else rotate(x,1); } else if(son[f[y]][1]==y) if(x==son[y][1]){ rotate(y,2);rotate(x,2); } else{ rotate(x,1);rotate(x,2); } else{ if(x==son[y][2]){ rotate(y,1);rotate(x,1); } else{ rotate(x,2);rotate(x,1); } } } root=x; } int search(int x,int w){ while(data[x]!=w){ if(w==data[x]) return x; if(w<data[x]){ if(son[x][1]==0) break; x=son[x][1]; } else{ if(son[x][2]==0) break; x=son[x][2]; } } return x; } void insert(int w){ bool flag; if(tot==0){ tot=1; f[1]=0;num[1]=1;data[1]=w;root=1;value[1]=1; return; } int k=search(root,w); int kk; if(data[k]==w){ value[k]++;kk=k; flag=1; } else{ tot++;data[tot]=w;f[tot]=k;value[tot]=1;num[tot]=1; if(data[k]>w) son[k][1]=tot; else son[k][2]=tot; flag=0; } while(k){ num[k]++; k=f[k]; } if(flag) splay(kk);else splay(tot); } int kth(int x,int w){ int i=root; while(!((x>=num[son[i][w]]+1)&&(x<=num[son[i][w]]+value[i]))&&(i!=0)){ if(x>num[son[i][w]]+value[i]){ x=x-num[son[i][w]]-value[i]; i=son[i][3-w]; } else i=son[i][w]; } int tmp=i; splay(i); return tmp; } int main(){ int last=1; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++){ int x; scanf("%d",&x); for(int j=last;j<=x;j++) insert(a[j]); last=x+1; printf("%d\n",data[kth(i,1)]); } }
时间: 2024-10-02 00:43:55