樹狀陣列 POJ2492 Ping Pong

2021-07-01 20:57:54 字數 2325 閱讀 5706

題意:按順序給定一些人和能量值。問按照順序選人,中間人能量值在兩邊人能量值的中間,問最多有多少種選法

思路:一次ac

有木有!其實是照著書上題解的思路打的。

設c[i]

為某a[i]

處左邊能量值比他小的人數和,

d[i]

為右邊能量值比他大的人數和,然後乙個簡單公式即可。關鍵是怎樣快速的求c[i]。

以a[i]

值建樹狀陣列,其中

c[i]

從前往後,

d[i]

從後往前(小創新,和書上不一樣雖然換湯不換藥),設存在的點

x[a[i]] = 1,

然後用不斷更新陣列的方式得到每個點的

c[i]

,d[i]

值。本題要求每個人能量值不重複,如果重複的話

x[i]

多加值就好。

不看知識點根本做不出來好嘛!其實可以這樣想:如何求前乙個區間和後乙個區間的數值和,除了線段樹,就是樹狀陣列了!

原始碼:#include 

#include 

#include 

#include 

#include 

#include 

using namespace std;

typedef long long ll;

int const maxn = 100000+5;

int a[maxn],c[maxn],d[maxn],x[maxn],sum[maxn];

int n,mmax,tmax;

ll res;

int gmax(int a,int b)

void init()

memset(c,0,sizeof(c));

memset(d,0,sizeof(d));

memset(x,0,sizeof(x));

memset(sum,0,sizeof(sum));

tmax = mmax = res = 0;

int lowbit(int l)

return l&-l;

int les(int aa)

int ans = 0;

//    printf("at first , aa = %d\n",aa);

while(aa>0){

//        printf("aa = %d\n",aa);

ans += sum[aa];

aa-=lowbit(aa);

return ans;

int big(int aa)

return les(mmax) - les(aa-1);

void add(int aa)

while(aa<=tmax){

sum[aa]+=1;

aa+=lowbit(aa);

void check()

int i;

printf("c = ");

for(i=0; iprintf("%d ",c[i]);

printf("\n d = ");

for(i=0; iprintf("%d ",d[i]);

printf("\n");

int main()

int t;

scanf("%d",&t);

while(t--){

init();

scanf("%d",&n);

for(int i=0; iscanf("%d",&a[i]);

tmax = gmax(tmax,a[i]);

for(int i=0; immax = gmax(mmax,a[i]);

x[a[i]] = 1;

add(a[i]);

c[i] = les(a[i]-1);

//        for(int i=1; i<=mmax; i++)

//            printf("%d ",sum[i]);

//        printf("\n");

mmax = 0;

memset(x,0,sizeof(x));

memset(sum,0,sizeof(sum));

for(int i=n-1; i>=0; i--){

mmax = gmax(mmax,a[i]);

x[a[i]] = 1;

d[i] = big(a[i]+1);

res += (n-i-1-d[i])*(i-c[i])+c[i]*d[i];

add(a[i]);

//        check();

printf("%i64d\n",res);

return 0;

樹狀陣列 hdu2492 Ping pong

如果是列舉參加比賽的人,那麼列舉起來就非常的複雜了 如果是列舉裁判,題目會變得簡單很多 假如裁判是第i個人,那麼參加比賽的肯定分別在i的左邊和i的右邊 那麼我就可以統計 1,i 1 這個區間內有多個人的rank小於等於i,i 1,n 這個區間內有多少人的rank大於等於i,兩者相乘,就是左邊小於等於...

HDU 2492 Ping pong 樹狀陣列

題目大意 一條大街上住著 n 個桌球愛好者,經常比賽切磋技術,每個人有乙個不同的技能值ai。每場比賽需要三個人,兩名選手,一名裁判。但是裁判必須住在兩名選手之間,而且裁判的技能值不能小於或小於兩名選手的技能值。問共有多少種比賽。思路 列舉裁判,找出位於裁判前面的比裁判技能小的人數和位於裁判後面技能比...

樹狀陣列POJ2155

poj 2155是一道很不錯的題目,表面上看,這題的要求似乎和樹狀陣列的使用方法恰好相反,改變的是乙個區間,查詢的反而是乙個點。實際上可以通過乙個轉化巧妙的解決。首先對於每個數a定義集合up a 表示 定義集合down a 表示。可以發現對於任何a於是對於這道題目來說,翻轉乙個區間 a,b 為了便於...