2020牛客寒假算法基礎集訓營4 H.坐火車(樹狀數組/線段樹)

感受網上的題解都略微簡略包括官方題解,因此打算寫一個儘量詳細的ios

題目連接:https://ac.nowcoder.com/acm/contest/3005/H數組

 

題意:spa

每一個車箱都有三個參數,color,l,r,詢問對於每一個車箱,在其兩邊的車箱有多少對車箱顏色相同,而且顏色的範圍在[li , ri]內code

思路: blog

首先咱們定義幾個數組,pre[i]表明整個數組的前綴中color[i]的個數,suf[i]表明整個數組的後綴中color[i]的個數,這讀入的過程當中咱們就先統計suf數組,樹狀數組sum[i]記錄每一個顏色的符合相求的對數是多少get

以後開始遍歷color[i],對於每一個color咱們計算以前咱們就在suf數組中減去它,這樣suf數組的意義就是在x以後各個顏色的個數string

以後咱們在樹狀數組中減去pre[color[i]]也就是在x以前與x顏色相同的車箱,由於統計的對數是要求在x的兩邊,因此咱們得減去與x匹配的個數it

而後就能夠在樹狀數組中查詢區間[li , ri]對數了io

在統計完以後就有很是重要的一步了,就是在樹狀數組中加入suf[color[i]]也就是i以後還有多少與i顏色相同的車箱,也就是i位置的貢獻了class

 

#include<iostream>
#include<algorithm>
#include<cstring>
 using namespace std;
 typedef long long ll;
 const int maxn=5e5+10;
 ll pre[maxn],suf[maxn],sum[maxn];
 int n,l[maxn],r[maxn],color[maxn];
 int lowbit(int x){return x&(-x);}
 void add(int x,int val)
 {
     while(x<=n){
         sum[x]+=val;
         x+=lowbit(x);
     }
 }
 ll query(int x)
 {
     ll ans=0;
     while(x>=1){
         ans+=sum[x];
         x-=lowbit(x);
     }
    return ans;
 }
 int main()
 {
     scanf("%d",&n);
     for(int i=1;i<=n;i++){
         scanf("%d%d%d",&color[i],&l[i],&r[i]);
         suf[color[i]]++;
     }
    for(int i=1;i<=n;i++){
        suf[color[i]]--;
        add(color[i],-pre[color[i]]);
        printf("%lld ",query(r[i])-query(l[i]-1));
        pre[color[i]]++;
        add(color[i],suf[color[i]]);
    }
    return 0;
 }
相關文章
相關標籤/搜索