2017.5.14-15 CPU监控 思考记录

        这题太TM不容易了      反复对拍调试了一下午+一晚上终于调出来了、、

        看起来很简单,但实际上坑、细节相当的多:

这题需要维护 正常的区间加、赋值操作之外,还需要维护历史最大连加、历史最大赋值

    

       所以pushdown异常恶心:

但因为上面的节点一定比下面的节点晚,所以可以用向下合并法  把上面的标记放到下面标记的后面考虑:

         而且很重要的是要分类讨论、、不要怕麻烦



pushdown时按照上图来就行了

但注意if和直接复制时出的错


犯的错误:1、没有分类讨论的习惯,老想一个代码完事(懒)

                    2、复制时<<忘了变成<<|

                    3、max2忘了赋初值

                    4、忘了+时赋值的合并





码:

#include<iostream>
#include<cstdio>
using namespace std;
#define zuo l,mid,o<<1 
#define you mid+1,r,o<<1|1
#define N 100004
int max1[N<<2],max2[N<<2],jia[N<<2],fuzhi[N<<2],a,b,c,n,q,m,op,ans,i,mj[N<<2],mf[N<<2];
char ch;
void up(int o)
{
		max1[o]=max(max1[o<<1],max1[o<<1|1]);                                max2[o]=max(max2[o],max1[o]);
}
void jian(int l,int r,int o)
{  fuzhi[o]=-999999999;                                                       mf[o]=-999999999; max2[o]=-999999999;
	if(l==r)
	{
		scanf("%d",&max1[o]);                                                 max2[o]=max1[o];
		return;
	}
	int mid=(l+r)>>1;
	jian(zuo);
	jian(you);
	up(o);
}
void down(int o)
{
// 合并法 
    max2[o<<1]=max(max2[o<<1],max1[o<<1]+mj[o]);max2[o<<1|1]=max(max2[o<<1|1],mf[o]);
    max2[o<<1|1]=max(max2[o<<1|1],max1[o<<1|1]+mj[o]);max2[o<<1]=max(max2[o<<1],mf[o]);
		if(mf[o<<1]!=-999999999)
		{
			//mj[o<<1]=max(jia[o<<1]+mj[o],mj[o<<1]);
			mf[o<<1]=max(mf[o<<1],max(mf[o],max1[o<<1]+mj[o]));
				
		} else if(mf[o<<1]==-999999999)
		{
			mj[o<<1]=max(jia[o<<1]+mj[o],mj[o<<1]);
			mf[o<<1]=mf[o];
		}
		if(mf[o<<1|1]!=-999999999)
		{
			//mj[o<<1]=max(jia[o<<1]+mj[o],mj[o<<1]);
			mf[o<<1|1]=max(mf[o<<1|1],max(mf[o],max1[o<<1|1]+mj[o]));
				
		} else if(mf[o<<1|1]==-999999999)
		{
			mj[o<<1|1]=max(jia[o<<1|1]+mj[o],mj[o<<1|1]);
			mf[o<<1|1]=mf[o];
		}		
//

if(fuzhi[o]!=-999999999)
{                                                                             	
		jia[o<<1]=jia[o<<1|1]=0;   
		fuzhi[o<<1]=fuzhi[o<<1|1]=fuzhi[o];                                      
		max1[o<<1]=max1[o<<1|1]=fuzhi[o];                                        
}
if(jia[o])
{
	if(fuzhi[o<<1]!=-999999999)fuzhi[o<<1]+=jia[o];
	else jia[o<<1]+=jia[o];
	if(fuzhi[o<<1|1]!=-999999999)fuzhi[o<<1|1]+=jia[o];
	else jia[o<<1|1]+=jia[o];
	max1[o<<1]+=jia[o];
	max1[o<<1|1]+=jia[o];	
}
jia[o]=0;                                                                          mj[o]=0;
fuzhi[o]=-999999999;                                                               mf[o]=-999999999;
}
void wen(int l,int r,int o)
{if(l!=r)down(o);
	if(a<=l&&r<=b)
	{
		if(op==1)
		{
			ans=max(ans,max1[o]);			
		}
		if(op==2)
		{
			ans=max(ans,max2[o]);			
		}		
		if(op==3)
		{
	      fuzhi[o]=c;                                                             mf[o]=max(mf[o],c);
	      jia[o]=0;                                                                
	      max1[o]=c;                                                              max2[o]=max(max2[o],mf[o]);
		}
		if(op==4)
    	{
	      if(fuzhi[o]==-999999999)
	      {
		  	jia[o]+=c;                                                             mj[o]=max(mj[o],jia[o]);
			max1[o]+=c;                                                            max2[o]=max(max2[o],max1[o]);
	      }else
	       {
	       	fuzhi[o]+=c;                                                           mf[o]=max(mf[o],fuzhi[o]);
			  max1[o]+=c;	       	                                               max2[o]=max(max1[o],max2[o]);
		   }
    	}				
		return;
	}	//	if(l!=r)down(o);
	int mid=(l+r)>>1;
	if(a<=mid)wen(zuo);
	if(b>mid)wen(you);	
	up(o);
}
int main()
{
scanf("%d",&n);
	jian(1,n,1);
scanf("%d",&q);
for(i=1;i<=q;i++)
{
	scanf("%c",&ch);while(ch=='\n')scanf("%c",&ch);
	if(ch=='Q')
	{
	scanf("%d%d",&a,&b);
	ans=-999999999;
	op=1;	
	wen(1,n,1);
	printf("%d\n",ans);
	}
     if(ch=='A')
	 {
	 		scanf("%d%d",&a,&b);
	ans=-999999999;
	op=2;	
	wen(1,n,1);
	printf("%d\n",ans);
     }
	 if(ch=='P')
    {
   	scanf("%d%d%d",&a,&b,&c);
	ans=-999999999;
	op=4;	
	wen(1,n,1);   	
   }	
   if(ch=='C')
   {
   	   	scanf("%d%d%d",&a,&b,&c);
	ans=-999999999;
	op=3;	
	wen(1,n,1);   	
   } 		
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值