buct寒假集训——树状数组

数星星

poj2352

#include <bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
tree<pair<int,int> ,null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update>tr;
typedef long long ll;
#define endl '\n'
const int N=15100;
 
vector<pair<int,int> >v(N);
int ans[N];
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int n;
    cin>>n;
    for( int i=0;i<n;i++){
        cin>>v[i].first>>v[i].second;
    }
    sort(v.begin(),v.begin()+n);
    int idx=0;
    for( int i=0;i<n;i++){
        int level=tr.order_of_key(make_pair(v[i].second+1,0));
        tr.insert(make_pair(v[i].second,++idx));
        ans[level]++;
         
    }
    for( int i=0;i<n;i++){
        cout<<ans[i]<<endl;
    }
 
}

公路交叉数

poj3067

#include <bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
#define endl '\n'
#define lowbit(x) x&(-x)
const int inf=0x3f3f3f3f;
const int K=10100;
int c[1010];
int query( int x){
    int sum=0;
    while(x>0){
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
void update( int i){
    while(i<=1000){
        c[i]++;
        i+=lowbit(i);
    }
}
int solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<pair<int,int> >v(K);
    for( int i=0;i<=1000;i++) c[i]=0;
    for( int i=0;i<k;i++){
        cin>>v[i].first>>v[i].second;
    }
    sort(v.begin(),v.begin()+k);
    int res=0;
    for( int i=0;i<k;i++){
        res+=query(1000)-query(v[i].second);
        update(v[i].second);
    }
    return res;
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int t;
    cin>>t;
    for( int i=1;i<=t;i++){
        printf("Test case %d: %d\n",i,solve());
    }
 
}

子树查询

poj3321
首先进行dfs求解时间戳,然后使用时间戳将树上的结点编号映射到一个一维数组中,使用树状数组维护一维数组。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define lowbit(x) x&(-x)
const int N=100100;
const int M=N+N;
int h[N],ne[M],to[M];
int idx;
int cnt[N],sz[N];//时间戳
int c[N];
int have_apple[N];
int n,m;
void add( int a,int b){
    to[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int idx2=0;
void dfs( int rt,int fa){
    cnt[rt]=++idx2;
    sz[rt]=1;
    for( int i=h[rt];i!=-1;i=ne[i]){
        int j=to[i];
        if(j==fa) continue;
        else{
            dfs( j,rt);
            sz[rt]+=sz[j];
        } 
    }
}
int query( int x){
    int sum=0;
    while(x>0){
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
void update( int i){
    int val=0;
    if(have_apple[i]==0) val=-1;
    else val=1;
    while(i<=n){
        c[i]+=val;
        i+=lowbit(i);
    }
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n;
    memset(h,-1,sizeof(h));
    for( int i=1;i<=n;i++){
        have_apple[i]=1;
        update(i);
    }
     
    for( int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        add(x,y);add(y,x);
    }
    dfs(1,-1);
    cin>>m;
    for( int i=1;i<=m;i++){
        string s;
        int q;
        cin>>s>>q;
         
        if(s=="C"){
            have_apple[cnt[q]]^=1;
            update(cnt[q]);
        }
        else {
            //cout<<cnt[q]+sz[q]+1<<" "<<cnt[q]-1<<endl;
            cout<<query(cnt[q]+sz[q]-1)-query(cnt[q]-1)<<endl;
        }
    }
    return  0;
}

矩形区间查询

poj1195
首先维护x,再维护y。
查询通过容斥原理进行查询。
发现模板有一个bug,update的下标不能从0开始,下标需要全部加一。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define lowbit(x) x&(-x)
const int N=1030;
int c[N][N];
int n;
int query( int x,int y){
    int sum=0;
    while(x>0){
        int yy=y;
        while(yy>0){
            sum+=c[x][yy];
            yy-=lowbit(yy);
        }
        x-=lowbit(x);
    }
    return sum;
}
void update( int x,int y,int val){
    while(x<=n){
        int yy=y;
        while(yy<=n){
            c[x][yy]+=val;
            yy+=lowbit(yy);
        }
        x+=lowbit(x);
    }
}
int main(){
    // ios_base::sync_with_stdio(0);
    // cin.tie(0); 
    // cout.tie(0);
    cin>>n>>n;
    while(1){
        int q;
        cin>>q;
        if(q==1){
            int x,y,val;
            cin>>x>>y>>val;
            ++x,++y;
            update(x,y,val);
        }
        else if(q==2){
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            ++x1,++x2,++y1,++y2;
            cout<<query(x2,y2)-query(x2,y1-1)-query(x1-1,y2)+query(x1-1,y1-1)<<endl;
        }
        else break;
    }
    return  0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值