首页 > 其他分享 >Codeforces Round #830 (Div. 2)

Codeforces Round #830 (Div. 2)

时间:2022-10-24 11:58:01浏览次数:49  
标签:830 xsum int sum mid Codeforces while Div ll

AB 太简单了,不写解法了。

CF1732C Sheikh

我们观察一下 \(f(l,r)=\mathrm{sum}(l,r)-\mathrm{xor}(l,r)\) 的性质。

考虑假如一个数 \(x\),对 \(\mathrm{sum}\) 的贡献为 \(x\),而对 \(\mathrm{xor}\) 的贡献小于等于 \(x\),因为可能异或和中已经有位为 \(1\)。

所以固定 \(l\),\(f(l,r)\) 单调递增,固定 \(r\) 也有此性质。

另一个显而易见的结论是假如不要求区间长度最小,\([L,R]\) 就是最终的答案,所以其实最大值已经确定为 \(f(L,R)\),只需要找长度最小的区间满足 \(f(l,r)=f(L,R)\) 即可。

由此结论,我们可以完成 C1,对于 \(i\in [L,R]\),先判断如果 \(j\) 取 \(R\) 也就是最大能不能达到 \(f(L,R)\),若能二分出使 \(f(i,j)\) 最大的 \(j_{\min}\),最后求出最小长度即可。

复杂度 \(O(Tnq\log n)\),其中 \(q=1\).


接下来考虑 C2,\(q\) 和 \(n\) 同阶,所以我们一次询问要求做到 \(O(\log n)\) 以内。

不知道有多少人可能想到过一个错误的做法:初始区间为 \([L,R]\),若左右端点能缩就缩。

我们规定 \(l_1=L\),\(l_1\) 为 \(R\) 作为右端点时区间满足 \(f=f(L,R)\) 左端点的最大值。

它错的原因是没有考虑每一个 \(l\in[l_1,l_2]\) 所对应的最小 \(r\),而是直接考虑了最大的 \(l=l_2\) 对应的最小 \(r\),从而遗漏了一些情况。

那么假如我们枚举每一个 \(l\in[l_1,l_2]\),然后二分的话,复杂度如何呢?

显然如果区间中 \(0\) 很多,一次询问就会被卡到 \(O(n\log n)\),这是我们不能接受的。

如果排除 \(0\) 的干扰,考虑答案区间 \([l,r]\),它满足加入 \(a_{l-1}\) 或 \(a_{r+1}\) 后值不变(前提时 \(L<l\leq r<R\)),说明 \(a_{l-1}\) 或 \(a_{r+1}\) 的二进制位在 \(\mathrm{xor}(l,r)\) 中都为 \(0\),那么最多有多少个这样的数呢,我们考虑每一个未加入的数都是 \(2^k\),约有 \(\log V\) 个。所以 \(l_2-l_1+1\) 是小于 \(\log V\) 的,复杂度就有了保证。

加上 \(0\) 的干扰,我们只需要预处理出每一个数前面和后面第一个非 \(0\) 数,然后枚举 \(l\in[l_1,l_2]\) 改成 \(l\) 从 \(L\) 及之后第一个非 \(0\) 数开始往后跳 \(l_2-l_1+1\) 次即可。

复杂度 \(O(Tq\log V\log n)\),但显然跑不满。

代码:

#include<bits/stdc++.h>
using namespace std;

#define int long long

inline int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c<='9'&&c>='0'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=1e5+5;
int T,n,q,a[N],sum[N],xsum[N];

int erfen1(int ll,int rr,int fmax){
	int l=ll,r=rr,mid;
	while(l<r){
		mid=l+r>>1;
		if(sum[mid]-sum[ll-1]-(xsum[mid]^xsum[ll-1])>=fmax)r=mid;
		else l=mid+1;
	}
	return l;
} 

int erfen2(int ll,int rr,int fmax){
	int l=ll,r=rr,mid;
	while(l<r){
		mid=l+r+1>>1;
		if(sum[rr]-sum[mid-1]-(xsum[rr]^xsum[mid-1])>=fmax)l=mid;
		else r=mid-1;
	}
	return l;
}

int nxt[N],pre[N];

signed main(){
	T=read();
	while(T--){
		n=read(),q=read();
		for(int i=1;i<=n;++i){
			a[i]=read();
			sum[i]=sum[i-1]+a[i];
			xsum[i]=(xsum[i-1]^a[i]);
		}
		int lst=0;
		for(int i=1;i<=n;++i){
			pre[i]=lst;
			if(!a[i])continue;
			lst=i;
		}
		lst=n+1;
		for(int i=n;i>=1;--i){
			nxt[i]=lst;
			if(!a[i])continue;
			lst=i;
		}
		while(q--){
			int L=read(),R=read();
			if(sum[R]==sum[L-1]){print(L),printf(" "),print(L),puts("");continue;}
			if(!a[L])L=nxt[L];
			if(!a[R])R=pre[R];
			int fmax=sum[R]-sum[L-1]-(xsum[R]^xsum[L-1]);
			int cnt=erfen2(L,R,fmax)-L+1,l=L,r=R,i=L;
			while(cnt--){
				if(sum[R]-sum[i-1]-(xsum[R]^xsum[i-1])<fmax)break;
				int j=erfen1(i,R,fmax);
				if(j-i<r-l)l=i,r=j;
				i=nxt[i];
				if(i>n)break;
			}
			print(l),printf(" "),print(r),puts("");
		}
	}
	return 0;
}

标签:830,xsum,int,sum,mid,Codeforces,while,Div,ll
From: https://www.cnblogs.com/Daidly/p/16821011.html

相关文章

  • Codeforces Round #829 (Div. 2) E Wish I Knew How to Sort
    WishIKnewHowtoSort概率dp设计一个\(dp[i]\)表示还需要进行\(i\)次有效移动的概率何为有效移动?最后的数组是\(0\)在左边,\(1\)在右边因此只有把两个在错误......
  • Codeforces Round #829 (Div. 2) D Factorial Divisibility
    FactorialDivisibility模拟合....合成大西瓜?枚举每个阶乘因子,提取公因式之后有很多散着的\(1\),然后判断能不能合成当前倍数#include<iostream>#include<cstdio>#......
  • Codeforces Round #829 (Div. 1/Div. 2) 1753 A B C D 题解
    Div1A/2C.MakeNonzeroSum令最后每个\(a_i\)的系数为\(c_i\)(\(c_i=1/-1\)),发现只要满足\(c_1=1\)(下标从1开始),且c中没有两个-1相连,就一定能找出一种划分方式。那我......
  • Codeforces Round #830 C1. Sheikh(Easy version)
    题意给定一个长为\(n\)的非负整数序列\(\{a_n\}\),求\(l,r\)使\(f(l,r)=\text{sum}(l,r)-\text{xor}(l,r)\)最大,若答案不唯一,使\(r-l\)尽可能小,若仍不唯一,输出任意答案。......
  • Codeforces Round #747 (Div. 2) D Educational Codeforces Round 115 D
    D.TheNumberofImposters显然我们对于每一个关系就相当于连一个无向边我们显然对于每一个连通块来讲我们确定其中一个也就确定了这个连通块里的所有就相当于二分图......
  • Codeforces Round #829 (Div. 2)
    咕咕咕。C2.MakeNonzeroSum(hardversion)易得有奇数个非零值时无解。现在考虑将相邻的两个非零值配对,只要每一个非零值对都搞成和为零,总的和就为零。由于非零值只......
  • Educational Codeforces Round 137 (Rated for Div. 2) A-F
    比赛链接A题解知识点:数学。\(4\)位密码,由两个不同的数码组成,一共有\(C_4^2\)种方案。从\(10-n\)个数字选两个,有\(C_{10-n}^2\)种方案。结果为\(3(10-n)(9-n)\)......
  • Codeforces Round #829 (Div. 2) D. Factorial Divisibility(数学)
    题目链接题目大意:\(~~\)给定n个正整数和一个数k,问这n个数的阶乘之和能不能被k的阶乘整除既:(a\(_{1}\)!+a\(_{2}\)!+a\(_{3}\)!+....+a\(_{n}\)!)\(~\)%\(~\)k!\(~\)==......
  • Codeforces 1682 D Circular Spanning Tree
    题意1-n排列,构成一个圆;1-n每个点有个值0或者1,0代表点的度为偶数,1代表点的度为计数;询问能否构成一棵树,树的连边在圆内不会相交,在圆边上可以相交,可以则输出方案。提示1.......
  • Codeforces Round #758 (Div.1 + Div. 2) C
    C.GameMaster//不明白为什么tag上没有二分我二分一下就过了我们显然知道判断是否能打赢全部直接通过连边来判断是否能遍历全部点如何连边:我们同组一定相连对于排......