您的位置:首页 > 其它

hdu 4970 树状数组区间更新 思维题

2014-08-22 23:18 411 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: