当 a 为 1 是输出第 k 小伤害值。
输入示例
5 5
1 3 5 7 9
1 4
0 6
1 4
0 5
1 4
输出示例
7
6
5
我以为插入的时候k也是50000以内,那就直接fenwick树解决,后来一问,范围好像是Int,那就只好用划分树或者平衡树了。
听同学说插入排序竟然过了。。。我刚也敲了一个,还真。。。。这数据得多水?
#include<cstdio> #include<algorithm> using namespace std; const int MAXN=100000+10; int a[MAXN]; int main() { int n,m,i; scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%d",&a[i]); sort(a,a+n); int cmd,k,len=n; for(i=0;i<m;i++) { scanf("%d%d",&cmd,&k); if(cmd==1) printf("%d\n",a[k-1]); else { //插入排序 int j; if(len==0) { a[0]=k; len++; continue; } for(j=len;j>=0;j--) { if(k < a[j-1]) a[j]=a[j-1]; else { a[j]=k; break; } } len++; } } }
#include<cstdio> #include<algorithm> using namespace std; const int MAXM=20; const int MAXN=100000+10; int data[MAXM][MAXN], num[MAXM][MAXN], sorted[MAXN]; struct node { int kind; //kind=0 代表插入 kind=1则为查询 int k; }p[MAXN]; void Build(int depth, int L, int R) { if (L == R) return; int same, mid, i, left, right; mid = (L + R) >> 1; same = mid - L + 1; left = L; right = mid + 1; for (i = L; i <= R; i++) { if (data[depth][i] < sorted[mid]) same--; } //same用来标记和中间值val_mid 相等的,且分到左孩子的数的个数。 for (i = L; i <= R; i++) { if (data[depth][i] < sorted[mid]) data[depth + 1][left++] = data[depth][i]; else if (data[depth][i] == sorted[mid] && same) { data[depth + 1][left++] = data[depth][i]; same--; } else data[depth + 1][right++] = data[depth][i]; num[depth][i] = num[depth][L - 1] + left - L; //num记录元素所在区间的当前位置之前进入左孩子的个数 } Build(depth + 1, L, mid); Build(depth + 1, mid + 1, R); } int findk(int L, int R, int x, int y, int k,int depth) { if (L == R) return data[depth][L]; int mid, left, temp; mid = (L + R) >> 1; left = num[depth][y] - num[depth][x - 1]; temp = num[depth][x - 1] - num[depth][L - 1]; if (left >= k) return findk( L, mid, L + temp, L + temp + left - 1, k,depth + 1); else { k -= left; temp = x - L - temp; left = y - x + 1 - left; return findk( mid + 1, R, mid + temp + 1, mid + temp + left, k,depth + 1); } } int main() { int n,m,i; int len=0; scanf("%d%d", &n,&m); for(i=0;i<n;i++) { scanf("%d",&p[i].k); len++; sorted[len] = data[0][len] = p[i].k; p[i].kind=0; //insert } int tot=n+m; for(;i<tot;i++) { int action; scanf("%d%d",&action,&p[i].k); if(action==0) { p[i].kind=0; len++; sorted[len] = data[0][len] = p[i].k; } else if(action==1) { p[i].kind=1; } } sort(sorted + 1, sorted + len + 1); Build(0, 1, len); int cnt=0; //统计当前元素个数 for(i=0;i<tot;i++) { if(p[i].kind==0) cnt++; else printf("%d\n",findk(1,len,1,cnt,p[i].k,0)); } return 0; }
记录它的左儿子个数,方便查询。
查询的时候大于左儿子个数向右查询 k=k-num-1,否则向左
#include<cstdio> struct node { node *left; node *right; int num; int cntL; node(){ left=right=NULL; cntL=0; } }; struct BST { node *root; BST() {root=NULL;} void insert(int num) { node *p=root,*p_fa=NULL; node *temp=new node; temp->num=num; while(p) { p_fa=p; if(num <= p->num) //left; { p->cntL++; p=p->left; } else //right p=p->right; } if(root==NULL) { root=temp; return; } if(num <= p_fa->num) p_fa->left=temp; else p_fa->right=temp; } int find(int k) { node *p=root; while(k!=p->cntL+1) { if(k> p->cntL) //大于就往右边查找 { k=k-p->cntL-1; p=p->right; } else { p=p->left; } } return p->num; } }bst; int main() { int n,m,i; scanf("%d%d",&n,&m); int cmd,k; for(i=0;i<n;i++) { scanf("%d",&k); bst.insert(k); } for(i=0;i<m;i++) { scanf("%d%d",&cmd,&k); if(cmd==0) bst.insert(k); else printf("%d\n",bst.find(k)); } return 0; }
SBT全称叫Size Balanced Tree,也是一种平衡树。
他既不SB也不BT。
关于SBT树我的介绍:Size Balanced Tree(SBT树)整理http://blog.csdn.net/murmured/article/details/17029131
这一次好多人都用这个。。。
#include<cstdio> const int MAXN=200000+10; struct SBT { int left[MAXN]; //left son int right[MAXN]; //right son int size[MAXN]; //the num of sons int value[MAXN]; //value int len; //length int root; SBT(){ root=len=0; } void right_rotate(int &t) { int k=left[t]; left[t]=right[k]; right[k]=t; size[k]=size[t]; size[t]=size[ left[t] ] + size[ right[t] ] +1; t=k; } void left_rotate(int &t) { int k=right[t]; right[t]=left[k]; left[k]=t; size[k]=size[t]; size[t]=size[left[t]]+size[right[t]]+1; t=k; } void insert(int &t,int v) { if(!t) { t=++len; value[t]=v; size[t]=1; left[t]=right[t]=0; return; } size[t]++; if(v < value[t]) insert(left[t],v); else insert(right[t],v); matain(t); } void matain(int &t) { if(size[ left[ left[t] ] ] > size[ right[t] ] ) { right_rotate(t); matain(right[t]); matain(t); } else if( size[ right[ left[t] ] ]>size[ right[t] ] ) { left_rotate(left[t]); right_rotate(t); matain(left[t]); matain(right[t]); matain(t); } else if(size[ right[ right[t] ] ]>size[ left[t] ]) { left_rotate(t); matain(left[t]); matain(t); } else if(size[ left[ right[t] ] ]>size[ left[t] ]) { right_rotate(right[t]); left_rotate(t); matain(left[t]); matain(right[t]); matain(t); } } int select(int t,int k) { if(k==size[left[t]]+1) return value[t]; if(k<=size[left[t]]) return select(left[t],k); else return select(right[t],k-size[left[t]]-1); } }sbt; int main() { int n,m,i; scanf("%d%d",&n,&m); int cmd,k; for(i=0;i<n;i++) { scanf("%d",&k); sbt.insert(sbt.root,k); } for(i=0;i<m;i++) { scanf("%d%d",&cmd,&k); if(cmd==0) sbt.insert(sbt.root,k); else printf("%d\n",sbt.select(sbt.root,k)); } return 0; }