首页 > 其他分享 >[CF1935E] Distance Learning Courses in MAC 题解

[CF1935E] Distance Learning Courses in MAC 题解

时间:2024-11-12 21:59:51浏览次数:1  
标签:lfloor Distance log mathit 题解 rfloor Courses sm 区间

[CF1935E] Distance Learning Courses in MAC

难度正常的一道题。

首先我们发现 “挑选若干个区间” 就是一句废话,因为按位或只会贡献答案而不会减小答案。所以我们需要在 \([L,R]\) 的每个区间都挑一个数,使得最终的按位或最大。

想办法让尽可能多的二进制位都变成 \(1\),且越是高位越好。但题目允许我们 \(O(n\log n)\) 的复杂度,直接想复杂度会出问题况且此题无部分分。所以考虑发现一些性质。比如这道题里,每个区间的数连续就是一个能很好配合按位或的性质。

因为数连续,不难想到对于每个区间 \([l_i,r_i]\),有且仅有两种情况:

  • \(\lfloor\log_2l_i\rfloor<\lfloor\log_2r_i\rfloor\),也就是说,在 \(l_i\) 和 \(r_i\) 之间存在一个 \(2\) 的整数次幂的数,设为 \(2^k\)。那么一定存在一个数 \(2^k-1\),这个数的二进制下的 \(0\sim\lfloor\log_2r_i\rfloor-1\) 位全部为 \(1\),且一定有若干个数满足第 \(\lfloor\log_2r_i\rfloor\) 位是 \(1\);
  • \(\lfloor\log_2l_i\rfloor=\lfloor\log_2r_i\rfloor\),则对于这个区间的所有数,第 \(\lfloor\log_2r_i\rfloor\) 位都是 \(1\)。

试将此结论推广到多个区间,对于任意编号为 \([L,R]\) 的区间和任意的区间最高位 \(F\in[0,\log_2V]\),设 \(l_i,r_i\) 的第 \(F\) 位均为 \(1\) 的区间个数为 \(\mathit{sm}_1\),而 \(l_i\) 的第 \(F\) 位是 \(0\)、\(r_i\) 的第 \(F\) 位是 \(1\) 的区间个数为 \(\mathit{sm}_2\)。则:

  • 若 \(\mathit{sm}_1>0\land\mathit{sm}_2=0\),则答案的第 \(F\) 位一定是 \(1\);
  • 若 \(\mathit{sm}_1=0\land\mathit{sm}_2=1\),则答案的第 \(F\) 位也一定是 \(1\);
  • 否则,答案的第 \(0\sim F\) 位都是 \(1\)。
  • 最后非常重要的一点,上述情况的必要条件是 \(\boldsymbol{\mathit{sm}_1>0\lor\mathit{sm}_2>0}\)。

到这里思路已经出来了:上文的 \(\mathit{sm}\) 数组可以前缀和处理区间和,然后从高到低遍历答案的每一位,按照上文的逻辑统计答案即可。

#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
	int x=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	int top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
constexpr int MAXN=2e5+5;
int T,F,n,q,sm1[MAXN][31],sm2[MAXN][31];
struct P{
	int l,r;
}p[MAXN];
int lss(int x){
	return 1<<__lg(x);
}
int max(int a,int b){
	return a>b?a:b; 
}

int main(){
	T=read();
	while(T--){
		n=read();
		for(int i=1;i<=n;++i){
			memset(sm1[i],0,sizeof(int)*(F+1));
			memset(sm2[i],0,sizeof(int)*(F+1)); 
		}
		for(int i=1;i<=n;++i){
			p[i]={read(),read()};
			if(lss(p[i].l)^lss(p[i].r)) p[i].l=0;
			F=max(F,__lg(p[i].r));
		}
		for(int i=1;i<=n;++i)
			for(int j=0;j<=F;++j){
				sm1[i][j]=sm1[i-1][j],sm2[i][j]=sm2[i-1][j];
				if(p[i].l&(1<<j)&&p[i].r&(1<<j)) ++sm1[i][j];
				if(!(p[i].l&(1<<j))&&p[i].r&(1<<j)) ++sm2[i][j];
			}
		q=read();
		while(q--){
			int l=read(),r=read(),ans=0;
			for(int j=F;~j;--j)
				if(sm1[r][j]-sm1[l-1][j]||sm2[r][j]-sm2[l-1][j]){
					if(sm1[r][j]-sm1[l-1][j]&&!(sm2[r][j]-sm2[l-1][j]))
						ans|=1<<j;
					else if(!(sm1[r][j]-sm1[l-1][j])&&sm2[r][j]-sm2[l-1][j]==1)
						ans|=1<<j;
					else {
						ans|=(1<<(j+1))-1;
						break;
					}
				}
			write(ans,' ');
		}
		putchar('\n');
	}
	return fw,0;
}

标签:lfloor,Distance,log,mathit,题解,rfloor,Courses,sm,区间
From: https://www.cnblogs.com/laoshan-plus/p/18542732

相关文章

  • [USACO06NOV] Corn Fields G 题解
    题目链接[USACO06NOV]CornFieldsG题解这是一道典型的状压dp,对于\(M\)行\(N\)列的图,由于每个点只有\(1\)和\(0\)两种状态,我们将其压缩为一个长度为\(M\)的数组,数组(\(g\))的每一项\(g_{i}\)表示状态的二进制表示法表示的数(如\(101\)表示为\(5\)),我们预先处......
  • [CEOI2023] A Light Inconvenience 题解
    Description今年CEOI的开幕式上有一场精彩的火炬表演。表演者们站成一排,从\(1\)开始从左往右编号。每个表演者举着一根火炬,初始只有一个举着点燃的火炬的表演者。表演分为\(Q\)幕。在第\(a\)幕开始之前,要么\(p_a>0\)个表演者从右侧加入表演,他们的火炬是熄灭的;要么最......
  • gym103102H AND = OR 题解
    非常巧妙的一个题。我们首先考虑单组询问该怎么做。首先需要注意到一个结论,即设答案为\(x\),那么对于\(\forally<x\),\(y\)都应该放在与组;同样的,对于\(\forally>x\),\(y\)都应该放在与组。进一步的,我们观察在\(\text{popcount}\)上也有同样的性质,即对于\(\forally,......
  • 好题记录 [集训队互测 2023] 优惠购物 题解
    首先发现这个过程的限制比较多,那么考虑重新描述这个过程。令\(x_i\)表示在第\(i\)个物品上使用了\(x_i\)张券,那么一组\(x_{1\simn}\)就描述了一个方案。方便起见,令\(s_i\)为前i个物品买完后剩了几张券,那么有:\(s_0=m\)\(s_i=s_{i-1}+\lfloor\frac{a_i-......
  • 【题解】洛谷P7287: 「EZEC-5」魔法
    P7287「EZEC-5」魔法感觉好题有思维,但是我没认真读题,看到样例就我以为了,他让任意一个区间满足大于\(S\)即可不是全部。我们手搓一下样例就可以发现,对于加法我们不加白不加的话肯定全部的数都加上,乘法肯定要等到加完后才开始,这些都是贪心思路。然后就是开始搭配操作了,我遇到......
  • 题解:「2017 山东一轮集训 Day7」逆序对
    LibreOJ6077前置知识:生成函数、组合数先考虑平方怎么做。\(f_{i,j}\)表示处理了前\(i\)个值,逆序对有\(j\)个。显然可以转移到\(f_{i+1,j},f_{i+1,j+1},f_{i+1,j+2},...,f_{i+1,j+i}\)。然后发现这个东西是个很简单的递推,而且长得很生成函数,于是可以很自然的写成\[1\t......
  • 题解:[SCOI2016] 美味
    前置知识:可持久化线段树(主席树)洛谷3293[SCOI2016]美味问题有一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)。每次询问给你\(b\)、\(x\),你需要求出\(\max\{a_i+x\bigoplusb\}\)。\(1\lel\ler\len\le2\times10^5,0\lea_i,b,x<10^5\)首先,有\(l,r\)应该......
  • AtCoder Beginner Contest 378 题解
    AtCoderBeginnerContest378题解比赛链接A-Pairing贪心#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidShowball(){vector<int>a(5);for(inti=0;i<4;i++){intx;cin>>x;a[x]++;......
  • 题解:[XIX Open Cup, Grand Prix of Korea] Dev, Please Add This!
    前置知识:2-SAT题意[XIXOpenCup,GrandPrixofKorea]Dev,PleaseAddThis!在一张网格上有以下几种物品:空地(.)墙(#)星星(*)一个球(O)现在你要玩一个游戏。你可以让球朝上下左右某一个方向移动,但是一旦移动就必须走到底,也就是说直到前面是墙或者边界才能停。另外,如果你走......
  • 【题解】洛谷P7286:「EZEC-5」人赢
    P7286「EZEC-5」人赢可以想到对于每个数要找到比他大的数中下标最大的数,我们按照数的大小排序,我们维护原序列的一个指针,对于每个数如果比指针大那么就左移指针,可以思考下为什么:指针上的数比现在这个数要小那比后面的数都小,于是我们左移指针直到大于这个数,可以发现我们也在一直......