cf741 D2

题目链接:https://codeforces.ml/contest/1562/problem/D2

思路:可以发现结果只和区间和的奇偶有关。区间和为0时答案为零,区间和为奇数时,需要找到[ l , r ]之间的某个数pos,使得去掉pos后,前面的和等于后面的和,两区间抵消。记sum为前缀和,则有sum[ pos - 1] - sum[ l - 1 ] = sum [ r ] - sum [ l ],整理得sum[ r ] + sum[ l - 1 ] = sum[ i ] + sum[ i - 1 ],而对于每个区间[ l , r ],左侧为定值,只需要预处理时将sum[ i ] + sum[ i - 1 ]加入i桶中,查询时查询第一个大于等于l的下标即为pos。可以加入2*N作为偏移量,使得下标非负。区间和为偶数时,去掉最后一个数或第一个数,即可转化成奇数情况。

ac代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 3e5+5;

int t,n,q;
char ch[N];
int sum[N*10];
int a[N];
vector<int>v[N*4];
int main(){
	ios::sync_with_stdio (false);
	cin >> t;
	while(t--){
		for(int i = N*2-n*2;i < n*2+N*2;i++)v[i].clear();
		cin >> n >> q;
		for(int i = 1;i <= n;i++)cin >> ch[i];
		for(int i = 1;i <= n;i++){
			if(((i&1)&&(ch[i]=='+'))||((i&1)==0&&ch[i]=='-'))
				a[i] = 1;
			else a[i] = -1;
		}
		for(int i = 1;i <= n;i++)sum[i] = sum[i - 1] + a[i];
		for(int i = 1;i <= n;i++)v[sum[i]+sum[i-1]+2*N].push_back(i);
		while(q--){
			int l,r;
			cin >> l >> r;
			int ans = sum[r] - sum[l - 1];
			if(ans == 0)cout << 0 << endl;
			else{
				if(ans&1){
					cout << 1 << endl;
				}
				else {
					cout << 2 << endl << r << " ";
					r--; 
				}
				ans = sum[r] + sum[l - 1];
				cout << v[ans+2*N][lower_bound(v[ans+2*N].begin(),v[ans+2*N].end(),l)-v[ans+2*N].begin()]<<endl;
			}
			
		}
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值