1. 程式人生 > >hdu 4970 樹狀陣列區間更新 思維題

hdu 4970 樹狀陣列區間更新 思維題

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;
}