树状数组专题

BZOJ 1452 [JSOI2009]Count

这里写图片描述
对每个权值建一颗BIT

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m;
struct BIT{
    #define MAXN (300+1)
    int f[MAXN][MAXN]; 
    void add(int x,int y,ll v) {
        for(int i=x;i<=n;i+=i&(-i)) 
            for(int j=y;j<=m;j+=j&(-j)) 
                f[i][j]+=v;
    }
    ll qur(int x,int y) {
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
            for(int j=y;j;j-=j&(-j)) 
                v+=f[i][j];
        return v;
    }
}T[101];
int a[MAXN][MAXN];
int main()
{
//  freopen("bzoj1452.in","r",stdin);
//  freopen(".out","w",stdout);
    n=read(),m=read();
    For(i,100) MEM(T[i].f);
    For(i,n) For(j,m) {
        int c=read();
        T[c].add(i,j,1);    
        a[i][j]=c;
    }
    int q=read();
    while(q--) {
        int p=read();
        if (p==1) {
            int x=read(),y=read(),c=read();
            T[a[x][y]].add(x,y,-1);
            a[x][y]=c;
            T[a[x][y]].add(x,y,1);
        } else {
            int x1=read(),x2=read(),y1=read(),y2=read(),c=read();
            printf("%d\n",T[c].qur(x2,y2)-T[c].qur(x1-1,y2)-T[c].qur(x2,y1-1)+T[c].qur(x1-1,y1-1));
        }
    }
    return 0;
}

BZOJ 4240 有趣的家庭菜园

给一个数列,每次对调2个相邻的数,问最小对调几次使数列满足
对于任意2<=i<=N-1,以下两个条件至少满足一个:
1. 对于任意1<=j<=i-1,hj<=hi
2.对于任意i+1<=j<=N,hk<=hi

考虑把它们按高度排序插入BIT

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m;
struct BIT{
    #define MAXN (300000+1)
    int f[MAXN]; 
    void add(int x,ll v) {
        for(int i=x;i<=n;i+=i&(-i)) 
                f[i]+=v;
    }
    ll qur(int x) {
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
                v+=f[i];
        return v;
    }
}T;
pi a[MAXN];
int main()
{
//  freopen("bzoj4240.in","r",stdin);
//  freopen(".out","w",stdout);
    n=read();
    For(i,n) {
        a[i]=mp(read(),i);
    }
    MEM(T.f)
    sort(a+1,a+1+n,greater<pi >());
    ll ans=0; int hea=1;
    For(i,n) {
        if(i>1&&a[i].fi!=a[i-1].fi) {
            while(i!=hea) T.add(a[hea++].se,1);
        }
        ll p=T.qur(a[i].se);
        ans+=min(p,hea-1-p);
    }
    cout<<ans<<endl;
    return 0;
}

BZOJ 3155 Preprefix sum

长度为n的数列,m次操作,包括单点修改,求前缀和的前缀和
1<=N,M<=100000

经典题

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m;
struct BIT{
    #define MAXN (5000000+10)
    ll f[MAXN]; 
    void add(int x,ll v) {
        for(int i=x;i<=n;i+=i&(-i)) 
                f[i]+=v;
    }
    ll qur(int x) {
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
                v+=f[i];
        return v;
    }
}T,T2;
ll a[MAXN];
int main()
{
//  freopen("bzoj3155.in","r",stdin);
//  freopen(".out","w",stdout);
    n=read();   m=read();
    MEM(T.f) MEM(T2.f)
    For(i,n) {
        a[i]=read();
        T.add(i,a[i]);
        T2.add(i,(ll)(n-i+1)*a[i]);
    }
    while(m--) {
        char s[10];
        scanf("%s",s);
        if (s[0]=='Q') {
            int x=read();
            printf("%lld\n",T2.qur(x)-T.qur(x)*(ll)(n-x));
        } else {
            int x=read(),v=read();
            T.add(x,(ll)v-a[x]);
            T2.add(x,(ll)(n-x+1) * ((ll)v-a[x]) );
            a[x]=v;
        }
    }
    return 0;
}

BZOJ 2762 [JLOI2011]不等式组

输入第一行为一个正整数 ,代表接下来有N 行。
接下来每一行可能有3种形式:
1.“Add a b c”,表明要往不等式组添加一条不等式 ax+b>c
2.“Del i”,代表删除第i 条添加的不等式(最先添加的是第1条)。
3.“Query k”,代表一个询问,即当x=k 时,在当前不等式组内成立的不等式的数量。
注意一开始不等式组为空,a,b,c,i,k 均为整数,且保证所有操作均合法,不会出现要求删除尚未添加的不等式的情况。

k的范围为 [106,106]

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int m;
const int n=2e6+10;
struct BIT{
    #define MAXN (3000000+10)
    ll f[MAXN]; 
    void add(int x,ll v) {
        x+=1e6+1;
        for(int i=x;i<=n;i+=i&(-i)) 
                f[i]+=v;
    }
    ll qur(int x) {
        x+=1e6+1;
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
                v+=f[i];
        return v;
    }
}T;
int l[MAXN],r[MAXN],sz=0;
bool B[MAXN]={0};
void Add() {
    ll a=read(),b=read(),c=read();
    ++sz;
    if (a>0) {
        int t=1+floor((double)(c-b)/a);
        if (t<=1e6) l[sz]=max(-(int)1e6,t),r[sz]=1e6;
        else B[sz]=1;
    } else if (a<0) {
        int t=-1+ceil((double)(c-b)/a);
        if (t>=-1e6) l[sz]=-1e6,r[sz]=min((int)1e6,t);
        else B[sz]=1;
    } else {
        if (b>c) l[sz]=-1e6,r[sz]=1e6;
        else B[sz]=1;
    }
    if (!B[sz]) {
        T.add(l[sz],1);
        if (r[sz]<1e6) T.add(r[sz]+1,-1);
    }
}
int main()
{
//  freopen("bzoj2762.in","r",stdin);
//  freopen(".out","w",stdout);
    m=read();
    MEM(T.f)
    while(m--) {
        char s[10];
        scanf("%s",s);
        if (s[0]=='Q') {
            int x=read();
            printf("%lld\n",T.qur(x));
        } else if (s[0]=='A') {
            Add();
        } else {
            int k=read();
            if (!B[k]) B[k]=1; else continue;
            T.add(l[k],-1);
            if (r[k]<1e6) T.add(r[k]+1,1);
        }
    }
    return 0;
}

BZOJ 1537 [POI2005]Aut- The Bus

平面上有k个整点上有值,现在找一条从 (1,1) (n,m) 的路径,使距离最短且经过的点值的和最大,求最大和

用树状数组维护最大值

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m,k;
struct BIT{
    #define MAXN (100000+10)
    ll f[MAXN]; 
    void tomax(int x,ll v) {
        for(int i=x;i<=n;i+=i&(-i)) 
                f[i]=max(f[i],v);
    }
    ll qur(int x) {
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
                v=max(v,f[i]);
        return v;
    }
}T;
int x[MAXN],y[MAXN],p[MAXN];
int hx[MAXN],hy[MAXN];
int find(int *h,int x,int sz) {return lower_bound(h+1,h+sz+1,x)-h;}
ll f[MAXN]={0};
int idx[MAXN];
bool cmp(int a,int b) {return (x[a]!=x[b])?(x[a]<x[b]):(y[a]<y[b]);}

int main()
{
    freopen("bzoj1537.in","r",stdin);
//  freopen(".out","w",stdout);
    n=read(),m=read(),k=read();
    MEM(T.f)
    For(i,k) {
        x[i]=read(),y[i]=read(),p[i]=read();
        hx[i]=x[i],hy[i]=y[i];
    }
    sort(hx+1,hx+1+k);  sort(hy+1,hy+1+k);
    int m1=unique(hx+1,hx+1+k)-hx,m2=unique(hy,hy+1+k)-hy;
    For(i,k) x[i]=find(hx,x[i],m1);
    For(i,k) y[i]=find(hy,y[i],m2);
    For(i,k) idx[i]=i;
    sort(idx+1,idx+1+n,cmp);
    ll ans=0;
    For(j,k) {
        int i=idx[j];
        f[i]=p[i]+T.qur(y[i]);
        ans=max(ans,f[i]);
        T.tomax(y[i],f[i]);
    }
    cout<<ans<<endl;
    return 0;
}

SPOJ DQUERY

查询一个区间中不同数的个数
询问离线,经典题

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m;
struct BIT{
    #define MAXN (30000+10)
    ll f[MAXN]; 
    void add(int x,ll v) {
        for(int i=x;i<=n;i+=i&(-i)) 
                f[i]+=v;
    }
    ll qur(int x) {
        ll v=0;
        for(int i=x;i;i-=i&(-i)) 
                v+=f[i];
        return v;
    }
}T;
ll a[MAXN];
int pos[1000000+10]={0};
pair<int,pi > q[200000+10];
int ans[200000+10];
int main()
{
//  freopen("spojDQUERY.in","r",stdin);
//  freopen(".out","w",stdout);
    n=read();   
    MEM(T.f) 
    For(i,n) {
        a[i]=read();
    }
    int m=read();
    For(i,m) q[i].se.fi=read(),q[i].se.se=i,q[i].fi=read(),q[i];
    sort(q+1,q+1+m);
    int p=1;

    For(i,q[m].fi) {
        if (pos[a[i]]) T.add(pos[a[i]],-1);
        pos[a[i]]=i;
        T.add(i,1);
        while(q[p].fi==i) {
            ans[q[p].se.se] = T.qur(n)-T.qur(q[p].se.fi-1);
            if (++p>m) break;
        }
    }
    For(i,m) printf("%d\n",ans[i]);

    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值