线段树30pts求Hack
查看原帖
线段树30pts求Hack
409774
Maysoul楼主2023/6/29 10:39

孩子从昨天调了一天了救救孩子吧QAQ

//2023/6/28
//别着急,先通读一遍题目
//别忘了开long long
//写完先看一遍怎么降复杂度
//要么开全局变量要么给定初值
//想想看,有什么情况需要特判
//看看数组开的够不够大
//std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int MAXN=1e5+10;
int num,ans;
struct node{
	int l,r;
	int mx,md;//md存放最大值在数组中的位置 
	int mark;
	node(){
		l=r=-1;
		mx=md=0;
		mark=0;
	}
}ts[4*MAXN];
int a[MAXN];
bool fyw[MAXN];//标记这个位置有无飞鱼丸 
void putup(int id)//得到最大值与最大值的坐标 
{
	int lcid=id*2;
	int rcid=lcid+1;
	if(ts[lcid].mx>ts[rcid].mx){
		ts[id].mx=ts[lcid].mx;
		ts[id].md=ts[lcid].md;
	}
	else{
		ts[id].mx=ts[rcid].mx;
		ts[id].md=ts[rcid].md;
	}
}
void putdown(int id,int len)//下放懒标记,正常模板 
{
	int lcid=id*2;
	int rcid=lcid+1;
	if(ts[id].mark==0) return;
	ts[lcid].mark+=ts[id].mark;
    ts[rcid].mark+=ts[id].mark;
    ts[lcid].mx+=ts[id].mark;
    ts[rcid].mx+=ts[id].mark;
    ts[id].mark=0;
}
void build(int id,int l,int r)//建树,正常模板 
{
	ts[id].l=l;
	ts[id].r=r;
	ts[id].mx=0;
	if(l==r) {
		ts[id].mx=a[l];
		ts[id].md=l;
	}
	else{
		int mid=l+(r-l)/2;
		int lcid=id*2;
		int rcid=lcid+1;
		build(lcid,l,mid);
		build(rcid,mid+1,r);
		putup(id);
	} 
}
void update(int id,int goal,int val)//操作1的单点修改 
{
	if(ts[id].l==ts[id].r){
		if(ts[id].l==goal) {
			ts[id].mx=val-ts[id].mx;
		}
		return;
	}
	int mid=(ts[id].l+ts[id].r)/2;
	int lcid=id*2;
	int rcid=lcid+1;
	if(goal<=mid) update(lcid,goal,val);
	if(goal>mid) update(rcid,goal,val);
	putup(id);
	return;
}
void zero(int id,int goal)//将2中的目标归零 
{
	if(ts[id].l==ts[id].r){
		if(ts[id].l==goal){
			num=ts[id].mx;//得到当前位置的能量 
			ts[id].mx=0;
		}
		return;
	}
	int mid=(ts[id].l+ts[id].r)/2;
	int lcid=id*2;
	int rcid=lcid+1;
	if(goal<=mid) zero(lcid,goal);
	if(goal>mid) zero(rcid,goal);
	putup(id);
}
void lineup(int id,int l,int r,int val)//操作3,区间修改正常模板 
{
	if(ts[id].l>=l&&ts[id].r<=r){
		ts[id].mark+=val;
		ts[id].mx+=val;
		return;
	}
	putdown(id,ts[id].r-ts[id].l+1);
	int mid=(ts[id].l+ts[id].r)/2;
	int lcid=id*2;
	int rcid=lcid+1;
	if(l<=mid) lineup(lcid,l,r,val);
	if(r>mid) lineup(rcid,l,r,val);
	putup(id);
}
int show(int id,int l,int r)//找所示区间的最值 
{
	int mid=(ts[id].l+ts[id].r)/2;
	int lcid=id*2;
	int rcid=lcid+1;
	if(ts[id].l>=l&&ts[id].r<=r)
	{
		int baka=ts[id].mx;
		zero(1,ts[id].md);//将最值归零 
		return baka;
	}
	putdown(id,ts[id].r-ts[id].l+1);
	int tot=INT_MIN;
	if(l<=mid) tot=max(tot,show(lcid,l,r));
	if(r>mid) tot=max(tot,show(rcid,l,r));
	return tot;
}
int main()
{
	int n,m,opt,x,l,r,v;
	std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin>>n>>m;
	for (int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	bool flag=0;
	for (int i=1;i<=m;i++){
		cin>>opt;
		if(opt==1){
			cin>>x>>v;
			update(1,x,v);//标记当前位置的飞鱼丸 
			fyw[x]=1;
		}
		else if(opt==2){
			cin>>l>>r;
			int hentai=0;
			for (int i=r;i>=l;i--)//在给定区间查找飞鱼丸 
			{
				if(fyw[i]) {
					fyw[i]=0;
					zero(1,i);//归零 
					hentai=num;
					flag=1;
					break;
				}
			} 
			if(!flag) hentai=show(1,l,r);//找不到飞鱼丸那就取区间最值 
			flag=0;
			ans+=hentai;
			cout<<hentai<<'\n';
		}
		else{
			cin>>l>>r>>v;
			lineup(1,l,r,v);//区间修改一下 
		}
	}
	if(ans<10000) cout<<"QAQ"<<'\n';
	else if(ans<10000000) cout<<"Sakura"<<'\n';
	else cout<<"ice"<<'\n';
	return 0;
}
2023/6/29 10:39
加载中...