51 15 17 13 35 5Sample Output12110HintThis problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.#----------------------------------------------------------------------------------------------#題目大意:按y的升序(y相同則按x升序)給出n(1<=n<=15000)個星星的坐標(0<=x,y<=32000),每個星星左下方(包括同一行或同一列)的星星個數為它的“等級”,依次輸出等級為1,2,3,...,n-1的星星的個數。
最后提示用sanf,最好不用cin
#----------------------------------------------------------------------------------------------#
思路很容易:樹狀數組求x的“順序對”,因為y已經按升序(即從低到高)排好序,所以只需要知道有多少個星星的x坐標小于當前星星的x坐標就可以了。
怎么用樹狀數組求x的“順序對”呢,先解釋下順序對就是它之前的數當中比它小的數的個數。
然后,就容易了:將星星的x坐標的位置+1,當然是樹狀數組的+1,然后,x的getsum就是它的等級了。
why?
因為:x坐標+1,就表示了x那一排多了1個,而y坐標是遞增的,每個點只有一個星星,所以當前x的getsum就代表了當前x坐標比它小的星星數量。
原諒我只能這樣描述……自己體會吧。
代碼:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lowbit(x) x&-xint n;int tr[32005];//樹狀數組int ans[15005];//存每個等級星星數void update(int q,int x){ for(int i=q;i<=32001;i+=lowbit(i))//注意i<=32001,這里我調了2天,之前寫的是i<=32000,然而我x++了,所以…… tr[i]+=x;}int getsum(int q){ int ans=0; for(int i=q;i>0;i-=lowbit(i)) ans+=tr[i]; return ans;}//模板int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); x++;//為了防止x為0 update(x,1); ans[getsum(x)-1]++;//前面x++了,后邊要減回來 } for(int i=0;i<n;i++) printf("%d/n",ans[i]);} By WZY
新聞熱點
疑難解答