題意:。。比較複雜,就是乙個樹有點權,乙個點的答案是子樹的所有點權的字首和的和(貪心思想轉換後的題意),問所有答案。
首先這是個假題解。。只是提供乙個思路。。。資料不強ac了。。。
思路:標解是個啟發式合併。。這裡嘗試另一種做法(因為不會),平均時間複雜度是nlogn^2。(資料弱。。)考慮合併操作複雜,我們可以分為合併暴力,單個兒子直接得答案兩種操作解決問題。(看起來很玄學。。),事實上是這樣的,單個兒子的時間複雜度不用解釋,肯定是正確的,我們只要維護子樹離散化後的個數以及乙個sum。對於暴力這部分。。其實也是一拍腦子想出來的。。首先有乙個二叉結點我們就要暴力他的子樹一次,當他是乙個滿二叉樹的時候,整個排序的過程就類似乙個歸併樹(事實上多乙個sort的log),那麼其實這個暴力就類似快排了,隨機資料下時間複雜度是科學的。。
**:#includeusing namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define bug puts("bug");
#define pb push_back
#define mp make_pair
#define x first
#define y second
typedef unsigned long long ll;
typedef pairpii;
const int maxn=1e5+100;
const int mod=1e9+7;
using namespace std;
ll sum;
int id[maxn],l[maxn],r[maxn],x,y,n,t,tim,cnt[maxn];
ll b[maxn],a[maxn],hs[maxn],bit[maxn],ans[maxn],sbit[maxn];
vectorv[maxn];
void add(int x,int y)
int dfs(int x,int f)
modify(id[x],1,bit);
modify(id[x],a[x],sbit);
}int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
tim=1;
mem(sbit,0),mem(bit,0);mem(ans,0);mem(cnt,0);
for(int i=0;i<=n+2;i++) v[i].clear();
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) hs[i]=a[i];
sort(hs+1,hs+n+1);
int n=unique(hs+1,hs+n+1)-hs;
for(int i=1;i<=n;i++) id[i]=lower_bound(hs+1,hs+n,a[i])-hs+1;
for(int i=0;i
hdu 3887 樹狀陣列
給你一棵樹,每個節點都有個編號。讓你求乙個節點他的子樹中編號比他小的節點有幾個。編號唯一,從1 n,已給出根節點 解 樹狀陣列統計。轉化為線性序列。可以想到的是,若要統計乙個節點,那麼比它小的孩子必須先插完,然後統計就行了。對於乙個節點i來說,只要把所有x那麼對於所有節點來說也是這樣的,從一開始插,...
hdu 3333 樹狀陣列
此題與3743相仿,但本題資料較大,需要用到離散化。如何去掉重複元素呢?採用離線演算法 首先將詢問按右端點從小到大排序,離線處理時,記錄每個元素所在位置,遇到重複元素時,從它之前出現的位置減去這個元素,這樣就是的每個元素總是出現在最後。include include include include ...
樹狀陣列 HDU1166
繼續上次那題,我們現在採用樹狀陣列來解。樹狀陣列主要用來進行區間求和統計和定點更新操作,樹狀陣列的儲存是如下方式的 假設陣列a為a 1 a 2 a 3 a n 現在我們另陣列c 1 a 1 c 2 a 1 a 2 c 3 a 3 c 4 a 1 a 2 a 3 a 4 這是啥結構呢?其實c i a ...