hdu 4970 樹狀陣列區間更新 思維題
阿新 • • 發佈:2019-01-09
http://acm.hdu.edu.cn/showproblem.php?pid=4970
好像還沒有用樹狀陣列寫過區間更新,但是樹狀陣列的確比線段樹快很多,不知道跟ZKW線段樹比效率怎麼樣:
先貼個模板:
#include <cstdio> const int MAXN = 1024; int B[MAXN], C[MAXN]; #define LOWBIT(x) ((x)&(-(x))) void bit_update(int *a, int p, int d) { for ( ; p && p < MAXN ; p += LOWBIT(p)) a[p] += d; } int bit_query(int *a, int p) { int s = 0; for ( ; p ; p -= LOWBIT(p)) s += a[p]; return s; } void bit_update2(int *a, int p, int d) { for ( ; p ; p -= LOWBIT(p)) a[p] += d; } int bit_query2(int *a, int p) { int s = 0; for ( ; p && p < MAXN ; p += LOWBIT(p)) s += a[p]; return s; } inline void _insert(int p, int d) { bit_update(B, p, p*d); bit_update2(C, p-1, d); } inline int _query(int p) { return bit_query(B, p) + bit_query2(C, p) * p; } inline void insert_seg(int a, int b, int d) { _insert(a-1, -d); _insert(b, d); } inline int query_seg(int a, int b) { return _query(b) - _query(a-1); } int main() { int com, a, b, c; while (scanf("%d%d%d",&com,&a,&b) != EOF) { a += 2; b += 2; //防止出現負數 if (com == 0) { //更新 scanf("%d",&c); insert_seg(a, b, c); } else { //查詢 printf("%d/n",query_seg(a,b)); } } return 0; }
本題比較裸,就是區間求和,然後查詢當前的monster 距離N之間殺傷的和,如果大於hi那麼怪物死去 500ms AC
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdout) const ll ll_INF = ((ull)(-1))>>1; const double EPS = 1e-8; const int INF = 100000000; const int MAXN = 100000+100; ll b[MAXN],c[MAXN]; int n,k,m; ll L[MAXN],r[MAXN],d[MAXN],h[MAXN],p[MAXN]; inline ll lowb(ll x){return x&(-x);} void init() { CL(b,0); CL(c,0); } void bitupdate(ll *a, ll p, ll d) { //////////////// //cout << "#update# " <<p << " " << d<<endl; ///////////////// while(p&&p<=n) { a[p]+=d; p+=lowb(p); } } void bitupdate2(ll *a, ll p,ll d) { //////////////// //cout << "#upda 222# " <<p << " " << d<<endl; ///////////////// while(p>0) { a[p]+=d; p-=lowb(p); } } ll bitquery(ll *a,ll p) { ll s=0; while(p) { s+=a[p]; p-=lowb(p); } return s; } ll bitquery2(ll *a, ll p) { ll s=0; while(p && p<=n) { s+=a[p]; p+=lowb(p); } return s; } inline void Insert(ll p, ll d) { bitupdate(b,p,p*d); bitupdate2(c,p-1,d); //////////////// //cout << "## " <<p << " " << d<<endl; ///////////////// } inline void insert_seg(ll x, ll y, ll d) { Insert(x-1,-d); Insert(y,d); } inline ll query(ll x) { return bitquery(b,x)+bitquery2(c,x)*x; } inline ll query_seg(ll a, ll b) { return query(b)-query(a-1); } int main() { // IN("hdu4970.txt"); ll ans=0; while(~scanf("%d",&n) && n) { init(); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%I64d%I64d%I64d",&L[i],&r[i],&d[i]); insert_seg(L[i],r[i],d[i]); } scanf("%d",&k); ans=0; for(int i=1;i<=k;i++) { scanf("%I64d%I64d",&h[i],&p[i]); ///////////////////////// //cout << "h[]" << i << " " << h[i] << "query " << query_seg(p[i],n) <<endl; ///////////////////////// if(query_seg(p[i],n)>=h[i])ans++; } printf("%I64d\n",k-ans); } return 0; }
標程的方法:
其實也是樹狀陣列的思想,但是我樹狀陣列還是不怎麼熟練啊 300ms AC
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #define maxn 100010 using namespace std; typedef long long ll; ll delta[maxn]; int main() { int n,m,l,r; ll v; while(scanf("%d",&n)&&n) { memset(delta,0,sizeof(delta[0])*(n+5)); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d%I64d",&l,&r,&v); delta[l]+=v; delta[r+1]-=v; } for(int i=2;i<=n;i++) { delta[i]+=delta[i-1]; } for(int i=n-1;i>=1;i--) { delta[i]+=delta[i+1]; } int ans=0; scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%I64d%d",&v,&r); if(v>delta[r]) ans++; } printf("%d\n",ans); } return 0; }