扶桑号战列舰【RMQ+分治】

扶桑号战列舰
时间限制: 1 Sec 内存限制: 128 MB Special Judge
提交: 197 解决: 63
[提交] [状态] [命题人:admin]
题目描述
众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据“个舰优越主义”,建造了扶桑级战列舰,完工时为当时世界上武装最为强大的舰只。
同时,扶桑号战列舰也是舰岛最为科幻的战列舰。
当然,要建造这样的舰船,科技水平是必须的。
同样众所周知的是,德意志科学技术天下第一,所以IJN的司令官从德国学来了一种先进的建船方法。
一只战舰横过来可以看做一个长度为n的序列,每个位置有一个数ai表示这个位置设计的高度。这种先进的造船技术可以每次将一个区间[l,r]内的所有位置高度都+1,求到达最终设计状态的最少操作次数。
如果你不能及时完成的话,IJN司令官会奖励你去参加苏里高海战。

输入
第一行包含一个整数n,表示序列的长度。
第二行包含n个非负整数a1,a2,a3,…,an,表示最终的状态。

输出
输出的第一行是一个正整数m,表示最少的操作次数。
接下来m行每行两个正整数li,ri,表示一次操作。
你需要保证1≤li≤ri≤n。
保证最少次数m≤105,输出可以以任意顺序输出。

样例输入
复制样例数据
6
2 3 3 3 3 3
样例输出
3
1 6
1 6
2 6

提示
在这里插入图片描述
解题思路:
通过RMQ维护区间最小值,然后在分治即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
typedef pair<int,int> p;
p dp[100100][25];
int arr[100100];
pair<int,int> res[100100];
void RMQ(int n) {
	for(int i=1;i<=n;i++) {
		dp[i][0].second=arr[i];
		dp[i][0].first=i;
	}
	for(int k=1;k<=(int)log2(n);k++) {
		for(int i=1;i+(1<<k)-1<=n;i++) {
			if(dp[i][k-1].second<=dp[i+(1<<(k-1))][k-1].second) {
				dp[i][k].second=dp[i][k-1].second;
				dp[i][k].first=dp[i][k-1].first;
			}
			else {
				dp[i][k].second=dp[i+(1<<(k-1))][k-1].second;
				dp[i][k].first=dp[i+(1<<(k-1))][k-1].first;
			}
		}
	}
}
p find(int l,int r) {
	int k=(int)log2(r-l+1);
	if(dp[l][k].second<=dp[r+1-(1<<k)][k].second) return dp[l][k];
	else return dp[r+1-(1<<k)][k];
}
int cnt;
void fenzhi(int l,int r,int num) {
	if(l>r) return;
	p nape=find(l,r);
	int t=nape.second;
	int mid=nape.first;
	for(int k=num+1;k<=t;k++) {
		cnt++;
		res[cnt].first=l;
    	res[cnt].second=r;
	}
	fenzhi(l,mid-1,t);
	fenzhi(mid+1,r,t);
}
int main() 
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    //freopen("out.txt", "w", stdout);
    //ios::sync_with_stdio(0),cin.tie(0);
    int n;
    scanf("%d",&n);
    rep(i,1,n) {
    	scanf("%d",&arr[i]);
    }
    RMQ(n);
    fenzhi(1,n,0);
    printf("%d\n",cnt);
    for(int i=1;i<=cnt;i++) {
    	printf("%d %d\n",res[i].first,res[i].second);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值