1. 程式人生 > 實用技巧 >mouseover(滑鼠覆蓋)與 mouseenter(滑鼠進入) mouseout和mouseleave的區別以及阻止冒泡的方法

mouseover(滑鼠覆蓋)與 mouseenter(滑鼠進入) mouseout和mouseleave的區別以及阻止冒泡的方法

題目連結:https://vjudge.net/problem/POJ-2182

題意:n頭牛,身高為1到n的一個排列。已知每頭牛前面比它矮的個數,求每頭牛的身高

這題和習題裡的poj2828基本一樣。倒著考慮,如果最後一頭牛前面有k1個比它矮,那麼它的身高就是k1+1。倒數第二頭如果有k2個比它矮,那麼它的身高是一個數(不等於k1+1),且滿足:比它小的而且沒出現過的數的個數為k2。等價於需要維護一個01序列,要求支援把1變成0的操作(是否出現過);求出一個數,它的字首和為某個值(有多少個數比當前的小)。單點修改和求字首和可以用樹狀陣列,快速求出這個數的位置用二分即可

#include<cstdio>
using namespace std;

const int N=8000+10;
int c[N],a[N],res[N],b[N],n,i,j,k,l,r;

void add(int x,int y){
	for (int i=x;i<=n;i+=i&(-i)) c[i]+=y;
}
int ask(int x){
	int res=0;
	for (int i=x;i>0;i-=i&(-i)) res+=c[i];
	return res;
}

int main(){
	scanf("%d",&n);
	for (i=1;i<=n;i++) add(i,1);
	for (i=2;i<=n;i++) scanf("%d",&a[i]);
	for (i=n;i>=2;i--){
	  l=0; r=n;
	  while (r-l>1){
	  	int m=(l+r)/2; 
	  	if (ask(m)<a[i]+1) l=m; else r=m;  //*
	  }
	  res[i]=r; b[r]=1; add(r,-1);
	}
	for (i=1;i<=n;i++) if (!b[i]) res[1]=i;
	for (i=1;i<=n;i++) printf("%d\n",res[i]);
	return 0;
}