2019年秋季学期第六周周任务——YCG

(为啥没有第五周?去问国庆。)

周任务:

算法任务:

朴素线段树

具体任务:

周任务
线段树就是一种比较超乎萌新(我)想象的数据结构吧,初识就觉得“哇,好难,好厉害的亚子”,用多了就觉得还好。它的关键在于一种区间的思想,lazy标记的使用的那种延迟下传的思想,能活用这种思想才是学习线段树的作用吧。

好用的板子千篇一律,有趣的bug万行难求。为了不影响各位的“找bug”或者“找我的板子到底和别人的板子有啥不同”的体验,我就不给模板了其实是自己没写
废话也不多说了——上代码。
hdu1166——敌兵布阵(单点修改,区间查询,树状数组同样适用)
代码:

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
const int maxn = 1e5+5;
int Tree[maxn<<2],T,N,ans;
string Str;
void BuildTree(int L,int R,int index){
    if(L==R){
     scanf("%d",&Tree[index]);
     return ;
 }
 int Mid = (L+R)>>1;
 BuildTree(L,Mid,index<<1);
 BuildTree(Mid+1,R,index<<1|1);
 Tree[index] = Tree[index<<1] + Tree[index<<1|1]; 
}
void pAdd(int p,int v,int index,int L,int R){
  if(L==R){
   Tree[index]+=v;
  return;
  }
  int Mid = (L+R)>>1;
  if(p<=Mid)pAdd(p,v,index<<1,L,Mid);
  else pAdd(p,v,index<<1|1,Mid+1,R);
  Tree[index] = Tree[index<<1]+Tree[index<<1|1];
}
void dQuery(int l,int r,int index,int L,int R){
   if(l<=L&&R<=r){
    ans+=Tree[index];
    return;
   }
   int Mid = (L+R)>>1;
   if(l<=Mid)dQuery(l,r,index<<1,L,Mid);
   if(r>Mid)dQuery(l,r,index<<1|1,Mid+1,R);
}
int main(){
 scanf("%d",&T);
 int cnt = 0;
 while(T--){
  cnt++;
  printf("Case %d:\n",cnt);
  scanf("%d",&N);
 BuildTree(1,N,1);
  while(1){
  cin >> Str;
  if(Str=="Query"){
   int l,r;
   scanf("%d%d",&l,&r);
   ans = 0;
   dQuery(l,r,1,1,N);
   printf("%d\n",ans);
  }
  else if(Str=="Add"){
   int p,v;
   scanf("%d%d",&p,&v);
   pAdd(p,v,1,1,N);
  }
  else if(Str=="Sub"){
   int p,v;
   scanf("%d%d",&p,&v);
   pAdd(p,-v,1,1,N);
  }
  else break;
   }
 }
 return 0;
}

hdu1754——I Hate It(区间最值,RMQ同样适用(空间不爆的话))
代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 2e5+5;
int N,Q,Tree[maxn<<2],ans;
void BuildTree(int L,int R,int index){
   if(L==R){
    scanf("%d",&Tree[index]);
    return;
   }
   int Mid = (L+R)>>1; 
   BuildTree(L,Mid,index<<1);
   BuildTree(Mid+1,R,index<<1|1);
   Tree[index] = max(Tree[index<<1],Tree[index<<1|1]);  
}
void dQuery(int l,int r,int L,int R,int index){
 if(l<=L&&R<=r){
  ans = max(Tree[index],ans);
  return; 
 }
 int Mid = (L + R)>>1;
 if(l<=Mid)dQuery(l,r,L,Mid,index<<1);
 if(r>Mid)dQuery(l,r,Mid+1,R,index<<1|1);
}
void pChange(int p,int v,int L,int R,int index){
 if(L==R){
  Tree[index] = v;
  return; 
 }
 int Mid = (L+R)>>1;
 if(p<=Mid)pChange(p,v,L,Mid,index<<1);
 else pChange(p,v,Mid+1,R,index<<1|1);
 Tree[index]  = max(Tree[index<<1],Tree[index<<1|1]); 
 
}
int main(){
 while(~scanf("%d%d",&N,&Q)){
      BuildTree(1,N,1);
   for(int i = 1;i <= Q;i++){
    string Str;
    cin >> Str;
    if(Str=="Q"){
     int l,r;
     ans = 0;
     scanf("%d%d",&l,&r);
     ans = 0;
     dQuery(l,r,1,N,1);
      printf("%d\n",ans);
    }
    else {
     int p,v;
     scanf("%d%d",&p,&v);
     pChange(p,v,1,N,1);
    }
   } 
 }
 return 0;
}

hdu1698——Just a Hook(区间修改,直接改掉的那种,维护整个区间的和,lazy标记不需要再查询时下传)
代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1e5+5;
int N,M,Tree[maxn<<2];
int Tag[maxn<<2];

void BuildTree(int L,int R,int index){
	Tag[index] = 0;
	if(L==R){
		Tree[index] = 1;	
		return;
	}
	int Mid = (L + R)>>1;
	BuildTree(L,Mid,index<<1);
	BuildTree(Mid+1,R,index<<1|1);
	Tree[index] = Tree[index<<1] + Tree[index<<1|1];	
}
void updata(int L,int R,int index){
	 int  Mid = (L + R)>>1;
	 Tag[index<<1] = Tag[index];
	 Tag[index<<1|1] = Tag[index];
	 Tree[index<<1] = Tag[index]*(Mid - L + 1);
	 Tree[index<<1|1] = Tag[index]*(R - Mid);
	 Tag[index] = 0;
	  
}
void dChange(int l,int r,int v,int L,int R,int index){
	if(l<=L&&R<=r){               
		Tree[index] = (R - L + 1) * v;
		Tag[index] = v;
		return;
	}
	if(Tag[index])updata(L,R,index);
	int Mid =(L + R)>>1;
	if(l<=Mid)dChange(l,r,v,L,Mid,index<<1);
	if(r>Mid)dChange(l,r,v,Mid+1,R,index<<1|1);
	Tree[index] = Tree[index<<1] + Tree[index<<1|1];
}
int main(){
	int T,cnt = 0;
	scanf("%d",&T);
	while(T--){
		cnt++;
		scanf("%d%d",&N,&M);
		BuildTree(1,N,1);
		for(int i = 1;i <= M;i++){
			int l,r,v;
			scanf("%d%d%d",&l,&r,&v);
			dChange(l,r,v,1,N,1);
		}
		printf("Case %d: The total value of the hook is %d.\n",cnt,Tree[1]);
	}
	return 0;
}

POJ3468——A Simple Problem with Integers(区间修改,区间查询,查询时记得下传lazy标记)

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
ll N,Opt,Tree[maxn<<2],Tag[maxn<<2],ans;
void BuildTree(int L,int R,int index){
	if(L==R){
		scanf("%lld",&Tree[index]);
		return;
	}
	int Mid = (L + R)>>1;
	BuildTree(L,Mid,index<<1);
	BuildTree(Mid+1,R,index<<1|1);
	Tree[index] = Tree[index<<1] + Tree[index<<1|1];
}
void Updata(int L,int R,int index){
	  int Mid = (L + R)>>1;
	  Tag[index<<1] += Tag[index];
	  Tag[index<<1|1] += Tag[index];
	  Tree[index<<1] += (Mid - L + 1)*Tag[index];
	  Tree[index<<1|1] += (R - Mid)*Tag[index];
	  Tag[index] = 0;
} 
void dQuery(int l,int r,int L,int R,int index){
	if(l<=L&&R<=r){
		ans+=Tree[index];
	     return;
	}
	if(Tag[index])Updata(L,R,index);
	int Mid = ( L +  R )>>1;
	if(l<=Mid)dQuery(l,r,L,Mid,index<<1);
	if(Mid<r)dQuery(l,r,Mid+1,R,index<<1|1);
}
void dChange(int l,int r,int v,int L,int R,int index){
	if(L>=l&&R<=r){
		Tree[index] += (R - L + 1)*v;
		Tag[index] += v;
		return; 
	}
	if(Tag[index])Updata(L,R,index);
	int Mid = (L + R)>>1;
	if(l<=Mid)dChange(l,r,v,L,Mid,index<<1);
	if(r>Mid)dChange(l,r,v,Mid+1,R,index<<1|1);
	Tree[index] = Tree[index<<1] + Tree[index<<1|1];
}
int main(){
	scanf("%lld%lld",&N,&Opt);
	BuildTree(1,N,1);
	string str;
	for(int i = 1;i <= Opt;i++){
	cin >> str;
	if(str=="Q"){
	int l,r;
	scanf("%d%d",&l,&r);
	ans = 0;	
	dQuery(l,r,1,N,1);
	printf("%lld\n",ans);
	}
	else{
	int l,r,v;
	scanf("%d%d%d",&l,&r,&v);
	dChange(l,r,v,1,N,1);	
	}
	} 
	return 0;
}

2019牛客多校训练营第四场C——sequence(单调栈确定每个数对应的最小值的区间,线段树维护区间最值,遍历每个数,算出每个数对应区间被改数数分为左右两个区间分别的最值的差值与该数的乘积)
讲解本题的博客(代码不同,不同时期写的嘛,大同小异,就是线段树的写法不同)
代码:

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
const int maxn = 3e6+5;
const ll INF = 1e18;
ll Tree1[maxn<<2],Tree2[maxn<<2],a[maxn],b[maxn],sum[maxn],S[maxn],cnt = 0,ans = -INF;
int N,L[maxn],R[maxn];

void BuildTree(int L,int R,int index){
	if(L==R){
		Tree1[index] = Tree2[index] = sum[++cnt];
		return;
	}
	int Mid = (L + R)>>1;
	BuildTree(L,Mid,index<<1);
	BuildTree(Mid+1,R,index<<1|1);
	Tree1[index] = max(Tree1[index<<1],Tree1[index<<1|1]);
	Tree2[index] = min(Tree2[index<<1],Tree2[index<<1|1]);
} 

ll Query1(int l,int r,int L,int R,int index){
	if(l<=L&&R<=r){
		return Tree1[index];
	}
	int Mid = (L + R)>>1;
	ll ans = -INF;
	if(l<=Mid)ans = max(ans,Query1(l,r,L,Mid,index<<1));
	if(r>Mid)ans = max(ans,Query1(l,r,Mid + 1,R,index<<1|1));
	return ans; 
	
}
ll Query2(int l,int r,int L,int R,int index){
	if(l<=L&&R<=r){
		return Tree2[index];
	}
	int Mid = (L + R)>>1;
	ll ans = INF;
	if(l<=Mid)ans = min(ans,Query2(l,r,L,Mid,index<<1));
	if(r>Mid)ans = min(ans,Query2(l,r,Mid + 1,R,index<<1|1));
	return ans; 	
}

int main(){
    scanf("%d",&N);
    N++;
    for(int i = 2;i <= N;i++){
        scanf("%lld",&a[i]);
    }
    sum[1] = 0;
     for(int i = 2;i <= N;i++){
        scanf("%lld",&b[i]);
        sum[i] = sum[i-1] + b[i];
    }
    int top = 0;//个人喜好,喜欢左右分别维护,可能测评姬抖的厉害的时候会卡住。
    for(int i = 2;i <= N;i++){
        while(top>0&&a[S[top]]>=a[i])top--;
        if(top==0)L[i] = 2;
        else L[i] = S[top] + 1;
        S[++top] = i;
    }
    top = 0;
    for(int i = N;i >= 2;i--){
        while(top>0&&a[S[top]]>=a[i])top--;
        if(top==0)R[i] = N;
        else R[i] = S[top] - 1;
        S[++top] = i;
    }
    BuildTree(1,N,1); 
    for(int i = 2;i<=N;i++){
    	ll p;
    	if(a[i]>0){
             p = (Query1(i,R[i],1,N,1) - Query2(L[i] - 1,i - 1,1,N,1));	  
		}
		else
		     p = (Query2(i,R[i],1,N,1) - Query1(L[i] - 1,i - 1,1,N,1));
		ans = max(ans,p*a[i]);
	}	
	printf("%lld\n",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值