牛客练习赛 95 C-Division(思维,差分)

传送门

思路:

首先把数组中数字取对数,替换成需要进行除2操作的次数,之后从左到右扫描数组,每次尽可能选取比较大的区间进行 -1 操作,如果尽可能大都不满足 r − l + 1 ≥ k r−l+1≥k rl+1k ,则输出 -1 ,在从左到右一次次清零过程中,为了操作次数最少,我们可以贪心的想,每次操作后形成的序列非递减就可以了,加大一次性选取的区间长度

代码:

#include <bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define eps 1e-7
using namespace std;

const double PI = acos(-1);
const int N = 3e5 + 10;

int n, k;

void solve(){
	cin >> n >> k;
	vector<int> a(n + 10, 0);
	vector<int> b(n + 10, 0);
	for (int i = 1; i <= n; i++){
		ll x;
		cin >> x;
		while(x)
			a[i]++, x >>= 1;
		a[i]--;
	}
	vector<pair<int, int>> ans;

	for (int i=1,j ; i <= n ;){
		if(!a[i])
			i++;
		else{
			for (j = i; j <= n && a[j] > a[j - 1]; j++)
				a[j]--;
			if (j - i < k){
				cout << -1 << '\n';
				return;
			}
			ans.push_back({i, j - 1});
		}
	}
	cout << ans.size() << '\n';
	for (auto item : ans)
		cout << item.first << " " << item.second << '\n';
}
int main(){
	int _ = 1;
	scanf("%d", &_);
	while (_--){
		solve();
	}
	return 0;
}

结合差分的题解:
在这里插入图片描述
标程:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
int a[20005],n,m,fs;
struct Thing{
	int l,r;
}ans[1000005];
void Clear(){
	for(int i=1;i<=n+1;i++)a[i]=0;
}
void Solve(){
	cin>>n>>m,fs=0;
	for(int i=1;i<=n;i++){
		ll x;
		cin>>x;
		while(x>1)x>>=1,a[i]++;
	}
	for(int i=n+1;i>=1;i--)a[i]-=a[i-1];
	stack<int> s;
	for(int i=1;i<=n+m;i++){
		if(i-m>=1){
			assert(a[i-m]>=0);
			while(a[i-m])s.push(i-m),a[i-m]--;
		}
		if(a[i]<0){
			while(a[i]){
				if(!s.size())return puts("-1"),Clear();
				ans[++fs]={s.top(),i-1},s.pop(),a[i]++;
			}
		}
	}
	if(s.size())return puts("-1"),Clear();
	cout<<fs<<'\n';
	for(int i=1;i<=fs;i++)cout<<ans[i].l<<' '<<ans[i].r<<'\n';
}
int main(){
	int t;
	cin>>t;
	while(t--)Solve();
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值