刚开始看到题目,想用memmove偷懒,结果TLE,后来查了查,才发现用memmove也是O(n^2)的复杂度。。。
#include <stdio.h> #include <string.h> int seq[222222]; int main() { int n,i,j,idx,posi,vali,t; while (~scanf("%d",&t)) { memset(seq,0,sizeof(seq)); for (i=0;i<t;i++) { scanf("%d%d",&posi,&vali); memmove(seq+posi+2,seq+posi+1,sizeof(int)*((i+1)-(posi+1))); seq[posi+1]=vali; } for (i=1;i<=t;i++) printf("%d ",seq[i]); printf("\b\n"); } return 0; }
在网上找了AC代码,还是没怎么看懂。
就知道是逆序遍历的,线段树结点存储的是当前区域的空位置数量。
关键是update函数中的代码看的不是很懂。
void update(int p,int l,int r,int rt){
...
if(Tree[rt<<1]>=p){
update(p,lson);
}else{
p-=Tree[rt<<1];
update(p,rson);
}
}
=======================================
五一和老婆玩了2天,现在趁着假期结尾把这道题搞明白了。也敢把AC的status贴上了、嘿嘿
初始状态
首先是插入3 69
1,4结点有4个位置,
1,2结点有2个位置,小于3,因此放到1,4结点右孩子,且1,4结点空位置减1
到了1,4右孩子后,只要找到第3-2=1个位置即可,而3,4结点的左孩子3,3含有1个空位置,1>=1,所以放到3,3位置了。
插入2 33
★关键是这里如何处理★
插入2 51
此时1,4的左孩子只有1个位置,1<2,所以只能放到1,4的右孩子3,4上
3,4的左孩子有0个位置,所以只能放在3,4的右孩子4,4上。
插入1 77
=======================================
Problem: 2828 | User: qq1203456195 | |
Memory: 4580K | Time: 1313MS | |
Language: C | Result: Accepted |
1 #include <stdio.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 #define maxn 222222 5 int Tree[maxn<<2]; 6 int Seq[maxn],Pos[maxn],Val[maxn]; 7 int id; 8 void build(int l,int r,int rt){ 9 int m=((l+r)>>1); 10 Tree[rt]=r-l+1; 11 if (l==r) 12 return; 13 build(lson); 14 build(rson); 15 } 16 void update(int p,int l,int r,int rt){ 17 int m=(l+r)>>1; 18 Tree[rt]--; 19 if (l==r){ 20 id=l; 21 return; 22 } 23 if(Tree[rt<<1]>=p){ 24 update(p,lson); 25 }else{ 26 p-=Tree[rt<<1]; 27 update(p,rson); 28 } 29 } 30 int main(){ 31 int n,i; 32 while(scanf("%d",&n)!=EOF) 33 { 34 build(1,n,1); 35 for (i=1;i<=n;i++) 36 scanf("%d%d",&Pos[i],&Val[i]); 37 for (i=n;i>=1;i--) 38 { 39 update(Pos[i]+1,1,n,1); 40 Seq[id]=Val[i]; 41 } 42 printf("%d",Seq[1]); 43 for (i=2;i<=n;i++) 44 printf(" %d",Seq[i]); 45 printf("\n"); 46 } 47 return 0; 48 }