CDOJ 1324 卿学姐与公主(分块)

题目链接

卿学姐与公主

Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

某日,百无聊赖的卿学姐打开了某11区的某魔幻游戏

在这个魔幻的游戏里,生活着一个美丽的公主,但现在公主被关押在了魔王的城堡中。

英勇的卿学姐拔出利刃冲向了拯救公主的道路。

走过了荒野,翻越了高山,跨过了大洋,卿学姐来到了魔王的第一道城关。

在这个城关面前的是魔王的精锐部队,这些士兵成一字排开。

卿学姐的武器每次只能攻击一个士兵,并造成一定伤害,卿学姐想知道某时刻从 L L R R这个区间内,从开始到现在累计受伤最严重的士兵受到的伤害。

最开始每个士兵的受到的伤害都是0

Input

第一行两个整数 N,Q N,Q表示总共有 N N个士兵编号从 1 1 N N,和 Q Q个操作。

接下来 Q Q行,每行三个整数,首先输入一个 t t,如果 t t 1 1,那么输入 p,x p,x,表示卿学姐攻击了 p p这个位置的士兵,并造成了 x x的伤害。如果 t t 2 2,那么输入 L,R L,R,表示卿学姐想知道现在 [L,R] [L,R]闭区间内,受伤最严重的士兵受到的伤害。

1N100000 1≤N≤100000

1Q100000 1≤Q≤100000

1pN 1≤p≤N

1x100000 1≤x≤100000

1LRN 1≤L≤R≤N

Output

对于每个询问,回答相应的值

Sample input and output

Sample Input Sample Output
5 4
2 1 2
1 2 4
1 3 5
2 3 3
0
5

Hint

注意可能会爆int哦

Source

2016 UESTC Training for Data Structures


题解:
今天学了一下分块,一个很暴力的算法,不过能解决一些线段树做不了的东西,很好的算法。
这一题用线段树做用了109ms,用分块做100ms,看来复杂度差不多。

分块模版:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e6+100;
int belong[MAXN],l[MAXN],r[MAXN];
int num,block;
int n;
//num为分块个数
//belong[i]表示i属于哪一块
//block表示块的大小
//l[i]表示i这块的左端点位置
//r[i]表示i这块的右端点位置 
void build()
{
	block=sqrt(n);
	num=n/block;
	if(n%block) num++;
	for(int i=1;i<=num;i++)
	l[i]=(i-1)*block+1,r[i]=i*block;
	r[num]=n;
	for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
}

ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e5+100;
typedef long long ll;
int belong[MAXN],l[MAXN],r[MAXN];
ll res[MAXN],a[MAXN];
int num,block;
int n;
//num为分块个数
//belong[i]表示i属于哪一块
//block表示块的大小
//l[i]表示i这块的左端点位置
//r[i]表示i这块的右端点位置 
void build()
{
	block=sqrt(n);
	num=n/block;
	if(n%block) num++;
	for(int i=1;i<=num;i++)
	l[i]=(i-1)*block+1,r[i]=i*block;
	r[num]=n;
	for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
}
void update(int p,ll v)
{
	a[p]+=v;
	res[belong[p]]=max(res[belong[p]],a[p]);
}

ll query(int ll,int rr)
{
	long long ans=0;
	if(belong[ll]==belong[rr])
	{
		for(int i=ll;i<=rr;i++) ans=max(ans,a[i]);
		return ans;
	}
	for(int i=ll;i<=r[belong[ll]];i++) ans=max(ans,a[i]);
	for(int i=l[belong[rr]];i<=rr;i++) ans=max(ans,a[i]);
	for(int i=belong[ll]+1;i<=belong[rr]-1;i++) ans=max(ans,res[i]);
	return ans;
}
int main()
{
	int q;
	scanf("%d%d",&n,&q);
	memset(a,0,sizeof(a));
	memset(res,0,sizeof(res));
	build();
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int p;
			ll v;
			scanf("%d%lld",&p,&v);
			update(p,v);
		}
		else 
		{
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%lld\n",query(l,r));
		}
	}
	return 0;
}

用线段树做:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=1e5+100;
typedef long long ll;
struct node
{
	int l,r;
	ll mx;
}seg[MAXN*4];
void build(int i,int l,int r)
{
	seg[i].l=l,seg[i].r=r,seg[i].mx=0;
	if(l==r) 
	return;
	int m=(l+r)>>1;
	build(i*2,l,m);
	build(i*2+1,m+1,r);
}
void update(int i,int p,ll x)
{
	if(seg[i].l==seg[i].r)
	{
		seg[i].mx+=x;
		return;
	}
	int m=(seg[i].l+seg[i].r)>>1;
	if(p<=m) update(i*2,p,x);
	else update(i*2+1,p,x);
	seg[i].mx=max(seg[i*2].mx,seg[i*2+1].mx);
}
ll query(int i,int l,int r)
{
	if(seg[i].l==l&&seg[i].r==r)
	return seg[i].mx;
	int m=(seg[i].l+seg[i].r)>>1;
	if(r<=m) return query(i*2,l,r);
	else if(l>m) return query(i*2+1,l,r);
	else return max(query(i*2,l,m),query(i*2+1,m+1,r));
}
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int p;
			ll v;
			scanf("%d%lld",&p,&v);
			update(1,p,v);
		}
		else 
		{
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%lld\n",query(1,l,r));
		}
	}
	return 0;
}




























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值