NOIp 資料結構
阿新 • • 發佈:2018-11-07
一、樹狀陣列
#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;
}