爆0,都不知道错那...
  • 板块P2357 守墓人
  • 楼主小范
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/3/20 21:25
  • 上次更新2023/10/23 20:59:20
查看原帖
爆0,都不知道错那...
502161
小范楼主2023/3/20 21:25
package SloveQuestion;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class P2357 {
	public static StreamTokenizer cin=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	public static PrintWriter cout=new PrintWriter(new OutputStreamWriter(System.out));
	public static int nextInt() throws IOException
	{
		cin.nextToken();
		return (int) cin.nval;
	}
	
	public static long nextLong() throws IOException
	{
		cin.nextToken();
		return (long) cin.nval;
	}
	private static int maxn=(int) (2e5+10);
	private static long a[]=new long[maxn];
	private static long t[]=new long[maxn<<2];//线段树
	//建树
	private static void build(int k, int L, int R) {
		if(L==R)//叶子节点
		{
			lazy[k]=0;
			t[k]=a[L];
		}
		else
		{
			int m=L+((R-L)>>1);
			lazy[k]=0;
			build(k<<1,L,m);
			build(k<<1|1,m+1,R);//父节点等于左右子节点之和
			PushUp(k);
		}
	}
	
	private static void PushUp(int k)//修改父节点
	{
		t[k]=t[k<<1]+t[k<<1|1];
	}
	
	private static long lazy[]=new long[maxn<<2];
	private static void PushDown(int k,int l,int r)//懒标记
	{
		if(lazy[k]!=0)
		{
			lazy[k<<1]+=lazy[k];
			lazy[k<<1|1]+=lazy[k];
			int mid=l+((r-l)>>1);
			t[k<<1]+=(mid-l+1)*lazy[k];//更新左
			t[k<<1|1]+=(r-mid)*lazy[k];//更新右
			lazy[k]=0;
			//PushUp(k);
		}
	}
	/*
	 * 
	 * @param l(l,r)要修改的区间
	 * @param r
	 * @param v:增加的值
	 * @param L:(L,R)当前节点的范围
	 * @param R
	 * @param k:当前节点
	 * @return 
	 */
	private static void update(int l, int r, long v, int L, int R, int k) {
		if(l<=L&&r>=R)
		{
			lazy[k]+=v;
			t[k]+=(R-L+1)*v;return ;
		}
		else
		{
			PushDown(k,L,R);
			int m=L+((R-L)>>1);
			if(l<=L)
			{
				update(l,r,v,L,m,k<<1);//更新左子树
			}
			if(r>R)
			{
				update(l,r,v,m+1,R,k<<1|1);//更新右子树
			}
			PushUp(k);return ;
		}
	}
	/*
	 * 查询(l,r)区间和
	 * @param l
	 * @param r
	 * @param L(L,R)当前节点范围
	 * @param R
	 * @param k 当前节点
	 * @return
	 */
	private static long query(int l, int r, int L, int R, int k) {
		//System.out.println("*"+"l:"+l+" r:"+r+" L:"+L+" R:"+R+" k:"+k);
		if(l<=L&&r>=R)
		{
			return t[k];
		}
			long ans=0;
			PushDown(k,L,R);
			int mid=L+((R-L)>>1);
			//System.out.println("mid:"+mid);
			if(l<=mid)
				ans+=query(l,r,L,mid,k<<1);
			if(r>mid)
				ans+=query(l,r,mid+1,R,k<<1|1);
			return ans;
	}
	
	public static void main(String[] args) throws IOException
	{
		int n,m;
		n=nextInt();m=nextInt();
		for(int i=1;i<=n;i++)a[i]=nextLong();
		build(1,1,n);//建树
		int key;//选择 1-5
		int l,r;int v;
		for(int i=1;i<=m;i++)//m次操作
		{
			key=nextInt();
			if(key==1)//将 [l,r] 这个区间所有的墓碑的风水值增加v。
			{
				l=nextInt();r=nextInt();v=nextInt();
				update(l,r,v,1,n,1);
			}
			else if(key==2)//2.将主墓碑的风水值增加 k
			{
				v=nextInt();;
				update(1,1,v,1,n,1);
			}
			else if(key==3)//3.将主墓碑的风水值减少 k
			{
				v=nextInt();
				update(1,1,-v,1,n,1);
			}
			else if(key==4)//4.统计[l,r] 这个区间所有的墓碑的风水值之和
			{
				l=nextInt();r=nextInt();//(l,r)
				cout.println(query(l,r,1,n,1));
				//System.out.println(query(l,r,1,n,1));
			}
			else if(key==5)//5.求主墓碑的风水值
			{
				//(1,1)//test
				cout.println(query(1,1,1,n,1));
			}
			/*
			for(int j=1;j<=n;j++)
				cout.print(query(j,j,1,n,1)+" ");
				cout.println();*/
		}
		cout.flush();cout.close();return ;
	}

}

2023/3/20 21:25
加载中...