1. 程式人生 > >NOIp 資料結構

NOIp 資料結構

一、樹狀陣列

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500005;
#define ll long long
ll n,m,opt,b,c,tmp;
ll a[MAXN];
ll lowbit(ll x){return x&-x;}
ll que(ll x){
    ll ret=0;
    for(ll i=x;i>0;i-=lowbit(i))
        ret+=a[i];
    return ret;
}
void add(ll x,ll k){
    for(ll i=x;i<=n;i+=lowbit(i))
        a[i]+=k;
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++){
        scanf("%lld",&tmp);
        add(i,tmp);
    }   
    for(ll i=1;i<=m;i++){
        cin>>opt>>b>>c;
        if(opt==1){
            add(b,c);
        }
        if(opt==2){
            printf("%lld\n",que(c)-que(b-1));
        }
    }
    return 0;
}

二、樹狀陣列+差分

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500005;
#define ll long long
int n,m,opt;
ll tmp[MAXN],a[MAXN],b,c,d;
ll lowbit(ll x){return x&-x;}
void add(ll x,ll k){
    for(int i=x;i<=n;i+=lowbit(i))
        a[i]+=k;
}
ll que(ll x){
    ll ret=0;
    for(int i=x;i>0;i-=lowbit(i))
        ret+=a[i];
    return ret;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&tmp[i]);
    for(int i=1;i<=m;i++){
        cin>>opt;
        if(opt==1){
            cin>>b>>c>>d;
            add(b,d);
            add(c+1,-d);
        }
        if(opt==2){
            cin>>b;
            printf("%lld\n",que(b)+tmp[b]);
        }
    }
    return 0;
}

三、線段樹(區間加,區間乘,區間求和)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500005;
#define ll long long
ll t1[MAXN],t2[MAXN],a[MAXN],sum[MAXN];
int n,m,opt;
ll p,b,c,d;
ll lc(ll x){return x<<1;}
ll rc(ll x){return x<<1|1;}
void pushup(ll x){sum[x]=(sum[lc(x)]+sum[rc(x)])%p;}
void pushdown(ll l,ll r,ll x){
    ll c1=lc(x),c2=rc(x),mid=(l+r)>>1;
    t1[c1]=t1[c1]*t2[x]%p;
    t1[c2]=t1[c2]*t2[x]%p;
    t2[c1]=t2[c1]*t2[x]%p;
    t2[c2]=t2[c2]*t2[x]%p;
    sum[c1]=sum[c1]*t2[x]%p;
    sum[c2]=sum[c2]*t2[x]%p;
    t2[x]=1;
    t1[c1]=(t1[c1]+t1[x])%p;
    t1[c2]=(t1[c2]+t1[x])%p;
    sum[c1]=(sum[c1]+(mid-l+1)*t1[x])%p;
    sum[c2]=(sum[c2]+(r-mid)*t1[x])%p;
    t1[x]=0;
}
void build(ll l,ll r,ll x){
    t1[x]=0;t2[x]=1;
    if(l==r){
        sum[x]=a[l];
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,lc(x));
    build(mid+1,r,rc(x));
    pushup(x);
}
void mul(ll L,ll R,ll l,ll r,ll x,ll k){
    if(L<=l&&r<=R){
        t2[x]=t2[x]*k%p;
        t1[x]=t1[x]*k%p;
        sum[x]=sum[x]*k%p;
        return;
    }
    ll mid=(l+r)>>1;
    if(t1[x]!=0||t2[x]!=1)pushdown(l,r,x);
    if(L<=mid)mul(L,R,l,mid,lc(x),k);
    if(mid<R)mul(L,R,mid+1,r,rc(x),k);
    pushup(x);
}
void add(ll L,ll R,ll l,ll r,ll x,ll k){
    if(L<=l&&r<=R){
        t1[x]=(t1[x]+k)%p;
        sum[x]=(sum[x]+(r-l+1)*k)%p;
        return;
    }
    ll mid=(l+r)>>1;
    if(t1[x]!=0||t2[x]!=1)pushdown(l,r,x);
    if(L<=mid)add(L,R,l,mid,lc(x),k);
    if(mid<R)add(L,R,mid+1,r,rc(x),k);
    pushup(x);
}
ll que(ll L,ll R,ll l,ll r,ll x){
    ll ret=0;
    if(L<=l&&r<=R){
        return sum[x]%p;
    }
    if(t1[x]!=0||t2[x]!=1)pushdown(l,r,x);
    ll mid=(l+r)>>1;
    if(L<=mid)ret+=que(L,R,l,mid,lc(x));
    if(mid<R)ret+=que(L,R,mid+1,r,rc(x));
    return ret%p;
}

int main(){
    scanf("%d%d%lld",&n,&m,&p);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        scanf("%d",&opt);
        if(opt==1){
            scanf("%lld%lld%lld",&b,&c,&d);
            mul(b,c,1,n,1,d);
        }
        if(opt==2){
            scanf("%lld%lld%lld",&b,&c,&d);
            add(b,c,1,n,1,d);
        }
        if(opt==3){
            scanf("%lld%lld",&b,&c);
            printf("%lld\n",que(b,c,1,n,1));
        }
    }
    return 0;
}

四、單調佇列

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000005;
int n,k,a[MAXN],q[MAXN],p[MAXN];
void getmax(){
    int head=1,tail=0;
    for(int i=1;i<=n;i++){
        while(head<=tail&&q[tail]<=a[i])tail--;
        q[++tail]=a[i];p[tail]=i;
        while(p[head]<=i-k)head++;
        if(i>=k)printf("%d ",q[head]);
    }
}
void getmin(){
    int head=1,tail=0;
    for(int i=1;i<=n;i++){
        while(head<=tail&&q[tail]>=a[i])tail--;
        q[++tail]=a[i];p[tail]=i;
        while(p[head]<=i-k)head++;
        if(i>=k)printf("%d ",q[head]);
    }
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    getmin();
    printf("\n");
    getmax();
    printf("\n");
    return 0;
}