P1438 無聊的數列(線段樹,差分)
阿新 • • 發佈:2018-11-06
P1438 無聊的數列
題目背景
無聊的YYB總喜歡搞出一些正常人無法搞出的東西。有一天,無聊的YYB想出了一道無聊的題:無聊的數列。。。(K峰:這題不是傻X題嗎)
題目描述
維護一個數列{a[i]},支援兩種操作:
1、1 L R K D:給出一個長度等於R-L+1的等差數列,首項為K,公差為D,並將它對應加到a[L]~a[R]的每一個數上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,
a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。
2、2 P:詢問序列的第P個數的值a[P]。
輸入輸出格式
輸入格式:
第一行兩個整數數n,m,表示數列長度和操作個數。
第二行n個整數,第i個數表示a[i](i=1,2,3…,n)。
接下來的m行,表示m個操作,有兩種形式:
1 L R K D
2 P 字母意義見描述(L≤R)。
題解:
差分,線段樹
const int maxn = 1e6+11; int sum[maxn],lazy[maxn]; void pushup(int i) { sum[i] = sum[i<<1]+sum[i<<1|1]; } void pushdown(int i,int l,int r) { int mid = (l+r)>>1; if(!lazy[i])return; sum[i<<1] += (mid-l+1)*lazy[i]; sum[i<<1|1] += (r - mid)*lazy[i]; lazy[i<<1] += lazy[i]; lazy[i<<1|1] += lazy[i]; lazy[i] = 0; } void update(int i,int l,int r,int ql,int qr,int v) { if(ql <= l && qr >= r) { sum[i] += v*(r-l+1); lazy[i] += v; return; } pushdown(i,l,r); int mid = (l+r)>>1; if(ql<=mid)update(i<<1,l,mid,ql,qr,v); if(qr>mid)update(i<<1|1,mid+1,r,ql,qr,v); pushup(i); } int query(int i,int l,int r,int ql,int qr) { if(ql<=l && qr>=r)return sum[i]; pushdown(i,l,r); int mid = (l+r)>>1; int ans = 0; if(ql<=mid)ans+=query(i<<1,l,mid,ql,qr); if(qr>mid)ans+=query(i<<1|1,mid+1,r,ql,qr); return ans; } int a[maxn]; int main() { int n,m; cin>>n>>m; rep(i,1,n+1)scanf("%d",a+i); rep(i,1,m+1) { int op,l;scanf("%d%d",&op,&l); if(op == 1) { int r,k,d; scanf("%d%d%d",&r,&k,&d); update(1,1,n,l,l,k); if(r!=n)update(1,1,n,r+1,r+1,-(k+(r-l)*d)); if(r>l)update(1,1,n,l+1,r,d); } else printf("%d\n",a[l]+query(1,1,n,1,l)); } }
樹狀陣列:
#include<cstdio> #include<cstring> #include<algorithm> #define MAXN 100010 using namespace std; int a[MAXN][2],p[MAXN],n; int lowbit(int x) { return x&(-x); } void add(int x,int k,int d) { while(x<=n) { a[x][0]+=k; a[x][1]+=d; k+=d*lowbit(x); x+=lowbit(x); } } int sum(int x) { int ans=0,pos=x; while(pos) { ans+=a[pos][0]+(x-pos)*a[pos][1]; pos-=lowbit(pos); } return ans; } int main() { int x,i,l,r,k,d,s,m; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&p[i]); for(i=1;i<=m;i++) { scanf("%d",&s); if(s==1) { scanf("%d%d%d%d",&l,&r,&k,&d); add(l,k,d); add(r+1,-k-(r-l+1)*d,-d); } else { scanf("%d",&x); printf("%d\n",p[x]+sum(x)); } } return 0; }