程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ3928、LA4329樹狀數組

POJ3928、LA4329樹狀數組

編輯:C++入門知識

借此題試驗一下各種做法的效果~

這題為ACM2008北京站某題,介於簡單與中等之間,做出來,罰時不多基本可以銅了,所以這樣的題還必須得會,進階之路。

add(a[i]+1,1)這樣處理之後,再用sum(a[i])計算得出的便的確是比a[i]小的數目。結合樹狀圖進一步了解下。

樹狀數組異常的美妙~

 

add(a[i],1)後樹狀數組的改變或許很復雜。。

 

嗯嗯!!明白了。

 

若換成add(a[i],1)後結果要相應換為sum(a[i])-1;就相當於在a[i]處多加了1,後面的就相當於add(a[i]+1,1)呗~~,但耗時會增多30+MS


 
#include <iostream>   
#include <stdio.h>   
#include <string.h>   
using namespace std;  
const int maxn=100005;  
long long  c[maxn];  
int a[20005];  
long long temp[maxn];  
int lowbit(int x)  
{  
    return x&-x;  
}  
void add(int x,int y)  
{  
    while(x<=maxn)  
    {  
       c[x]+=y;  
       x+=lowbit(x);  
    }  
}  
long long sum(int x)  
{  
    long long ret=0;  
    while(x>0)  
    {  
        ret+=c[x];  
        x-=lowbit(x);  
    }  
    return ret;  
}  
int main()  
{  
    int case_num;  
    scanf("%d",&case_num);  
    while(case_num--)  
    {  
        memset(c,0,sizeof(c));  
        int n;  
        scanf("%d",&n);  
        for(int i=1;i<=n;i++)  
        {  
            scanf("%d",&a[i]);  
            add(a[i]+1,1);//自己再試一下只能0 1值的數組,結果類似,把+1換成+x[i]   
            temp[i]=sum(a[i]);//這地方減c[x]對不對。。   
        }  
        long long ans=0;  
        for(int i=1;i<=n;i++)  
           printf(" %d ",sum(a[i]));  
        printf("\n");  
        for(int i=2;i<n;i++)  
        {  
            ans+=temp[i]*(n-i-(sum(a[i])-temp[i]));//其實一開始sum(a[i])-temp[i]還不太確定   
            ans+=(i-1-temp[i])*(sum(a[i])-temp[i]);//我這個sum(a[i])到底包括本身不(不包括)   
        }  
        printf("%lld\n",ans);  
    }  
    return 0;  
}  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved