1. 程式人生 > >HDU 1166 - 敵兵布陣 - [分塊]

HDU 1166 - 敵兵布陣 - [分塊]

c代碼 code sqrt namespace cin 模板題 break clu www

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1166

題解:

本題作為一個模板題,我用它來檢驗過總查詢時間復雜度為 $O(q \log n)$ 的樹狀數組模板、線段樹模板以及zkw線段樹模板;而今天,我們要來用分塊來寫這道題目。

時間復雜度:

初始化 $O(n)$;每次修改均為 $O(1)$,每次查詢為 $O(\sqrt n)$;總時間復雜度 $O(n + q \sqrt n)$。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;

int n; int a[maxn],sum[maxn]; int block[maxn],len,tot; int L[maxn],R[maxn]; void init(int l,int r) { memset(sum,0,sizeof(sum)); len=sqrt(r-l+1); tot=0; for(int i=l;i<=r;i++) { block[i]=(i-l)/len+1; tot=max(block[i],tot); sum[block[i]]+=a[i]; if(i==l) L[block[i]]=i;
if(i==r) R[block[i]]=r; if(l<=i-1 && i<=r && block[i-1]!=block[i]) { R[block[i-1]]=i-1; L[block[i]]=i; } } } void add(int p,int x) { a[p]+=x; sum[block[p]]+=x; } int ask(int l,int r) { int st=block[l],ed=block[r];
int res=0; if(st==ed) for(int i=l;i<=r;i++) res+=a[i]; else { for(int i=l;i<=R[st];i++) res+=a[i]; for(int i=st+1;i<=ed-1;i++) res+=sum[i]; for(int i=L[ed];i<=r;i++) res+=a[i]; } return res; } int main() { int T; cin>>T; for(int kase=1;kase<=T;kase++) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); init(1,n); printf("Case %d:\n",kase); char op[6]; while(scanf("%s",op)) { if(op[0]==E) break; if(op[0]==Q) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",ask(l,r)); } else if(op[0]==A) { int pos,x; scanf("%d%d",&pos,&x); add(pos,x); } else if(op[0]==S) { int pos,x; scanf("%d%d",&pos,&x); add(pos,-x); } } } }

HDU 1166 - 敵兵布陣 - [分塊]