算法训练2

1.操作格子
有n个格子,从左到右放成一排,编号为1-n。
共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3

#include<bits/stdc++.h>
using namespace std;
int n,m;
int sum,ans;
int ac[200007];
struct node{
	int l,r,w;
}t[2000007],t2[2000007];
void build(int k,int l,int r){
	t[k].l=l;
	t[k].r=r;
	t2[k].l=l;
	t2[k].r=r;
	if(l==r) t[k].w=ac[l],t2[k].w=ac[l];
	else {
		int mid=(l+r)/2;
		build(k*2,l,mid);
    	build(k*2+1,mid+1,r);
    	t[k].w=max(t[k*2].w,t[2*k+1].w);
    	t2[k].w=t2[k*2].w+t2[2*k+1].w;
	}
}
void query(int x,int y,int k){
	if(x<=t[k].l && y>=t[k].r){
        sum=max(sum,t[k].w);
    }
    else {
    	int mid=(t[k].l+t[k].r)/2;
    	if(x>=mid+1) query(x,y,2*k+1);
    	else if(y<=mid) query(x,y,k*2);
    	else {
    		query(x,y,k*2);
            query(x,y,k*2+1);
		}
	}
}
void query2(int x,int y,int k){
	if(x<=t[k].l && y>=t[k].r){
        ans+=t2[k].w;
    }
    else {
    	int mid=(t2[k].l+t2[k].r)/2;
    	if(x>=mid+1) query2(x,y,2*k+1);
    	else if(y<=mid) query2(x,y,k*2);
    	else {
    		query2(x,y,k*2);
            query2(x,y,k*2+1);
		}
	}
}
void update(int x,int y,int k){
	if(t[k].l==t[k].r) {
		t[k].w=y;
		t2[k].w=y;
		return ;
	}
	int m=(t[k].l+t[k].r)/2;
	if(x>m) update(x,y,k*2+1);
	if(x<=m) update(x,y,k*2);
	t[k].w=max(t[k*2].w,t[2*k+1].w);
	t2[k].w=t2[k*2].w+t2[k*2+1].w;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
    {
        scanf("%d",&ac[i]);
    }
    build(1,1,n);
	int a,b;
    while(m--){
    	char ss;
    	cin>>ss;
    	if(ss=='3'){
    		cin>>a>>b;
    		sum=0;
            query(a,b,1);
            printf("%d\n",sum);
		}
		else if(ss=='1'){
			cin>>a>>b;
			update(a,b,1);
		}
		else {
			cin>>a>>b;
			ans=0;
			query2(a,b,1);
			printf("%d\n",ans);
		}
	}
}

2.SPFA
输入格式
第一行输入n,m;第二行输入begin,end
接下来m行输入x,y,z;
n表示点数,m表示边数,begin表示起始点,end表示目标点,x、y表示连同连点z表示权值
输出格式
  输出begin到end的最短路
样例输入
7 12
1 7
1 7 10
1 2 1
1 3 2
2 7 8
2 3 1
2 4 4
2 5 1
2 6 10
3 4 3
5 6 1
5 4 7
6 7 1
样例输出
4

#include<bits/stdc++.h>
using namespace std;
const int N = 100107;
const int M = 400107;
int n, m,begin,end;
int head[N], nex[M], to[M], val[M], ce;
void add(int u, int v, int w) {	
    to[++ce] = u; nex[ce] = head[v]; head[v] = ce; val[ce] = w;
    to[++ce] = v; nex[ce] = head[u]; head[u] = ce; val[ce] = w;
}
int d[N];
bool used[N];
queue<int> q;
void spfa(int s) {
    memset(d, 0x3f, sizeof d);
    d[s] = 0;
    q.push(s);
    used[s] = true;
    while(!q.empty()) {
        int u = q.front(); q.pop();
        used[u] = false;
        for(int i=head[u]; i; i=nex[i]) {
            int v = to[i], w = val[i];
            if(d[u] + w < d[v]) {
                d[v] = d[u] + w;
                if(!used[v]) {
                    used[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
int main(){
	cin>>n>>m>>begin>>end;
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
	}
	spfa(begin);
    printf("%d\n", d[end]);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值