首页 > 其他分享 >Codeforces 1456E - XOR-ranges

Codeforces 1456E - XOR-ranges

时间:2023-07-22 10:22:18浏览次数:41  
标签:1456E XOR r1 int ranges MAXN l1 l2 dp

考虑一个 \(L\le x\le R\) 的数 \(x\),必然是一段前缀贴着 \(L\) 或者 \(R\),然后下一位脱离了 \(L\) 和 \(R\) 的限制,后面随便乱填。

注意到一个性质,对于某一位 \(d\),考虑这一位上没有限制的那些位置,最优方案肯定是令其等于其左边(或者右边)第一个有限制的数的第 \(d\) 位上的值。这样对于每一位,我们只用考虑它有限制的那些位,计算相邻不同的数量。

这不难让我们想到区间 DP 的模型:\(dp_{x,l,r,0/1,0/1,0/1,0/1}\) 表示现在填好了 \(x\) 以下的位,当前区间为 \([l,r]\),\(l-1\) 是贴紧下界还是上界,\(l-1\) 最下面的位是否被翻转,\(r+1\) 是贴紧下界还是上界,\(r+1\) 最下面的位是否被翻转。考虑转移,如果没有恰好在 \(2^x\) 位脱离限制的位置,那就直接从 \(dp_{x+1,l,r}\) 转移过来,否则我们枚举这个位置 \(k\) 然后从 \(dp_{x,l,k-1}+dp_{x,k+1,r}\) 转移即可。

使用记忆化搜索实现很方便。时间复杂度 \(n^4\)。

const int MAXN=50;
const ll INF=1e18;
int n,k;ll L[MAXN+5],R[MAXN+5],c[MAXN+5],dp[MAXN+5][MAXN+5][MAXN+5][2][2][2][2];
ll calc(int x,int l,int r,int l1,int l2,int r1,int r2){
	if(x==k)return (l>r)?0:INF;
	if(~dp[x][l][r][l1][l2][r1][r2])return dp[x][l][r][l1][l2][r1][r2];
	int lb=(((l1)?R[l-1]:L[l-1])>>x&1)^l2;
	int rb=(((r1)?R[r+1]:L[r+1])>>x&1)^r2;
	ll &ret=dp[x][l][r][l1][l2][r1][r2];
	ret=calc(x+1,l,r,l1,0,r1,0)+((l!=1&&r!=n&&lb!=rb)?c[x]:0);
	for(int k=l;k<=r;k++)for(int t=0;t<2;t++){
		if(!x)chkmin(ret,calc(x,l,k-1,l1,l2,t,0)+calc(x,k+1,r,t,0,r1,r2));
		ll w=t?R[k]:L[k],_l=(w^(1ll<<x))&(~((1ll<<x)-1)),_r=(w^(1ll<<x))|((1ll<<x)-1);
		if(L[k]<=_l&&_r<=R[k])chkmin(ret,calc(x,l,k-1,l1,l2,t,1)+calc(x,k+1,r,t,1,r1,r2));
	}return ret;
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%lld%lld",&L[i],&R[i]);
	for(int i=0;i<k;i++)scanf("%lld",&c[i]);
	memset(dp,-1,sizeof(dp));printf("%lld\n",calc(0,1,n,0,0,0,0));
	return 0;
}

标签:1456E,XOR,r1,int,ranges,MAXN,l1,l2,dp
From: https://www.cnblogs.com/tzcwk/p/Codeforces-1456E.html

相关文章

  • AGC034F RNG and XOR
    类似随机游走,令\(f_i\)为第一次操作到\(i\)的期望操作次数,\(p_i\)为每次操作数为\(i\)个概率,显然有:\[f_i=\begin{cases}0&i=0\\1+\sum\limits_{j\;\text{xor}\;k\=\i}p_jf_k&i\neq0\end{cases}\]显然可以高斯消元,不过是\(O(2^{3n})\)的,寄飞。考虑到转移过程中有......
  • CF1083F The Fair Nut and Amusing Xor
    简要题意:给你两个序列\(a,b\),一次操作可以将\(a\)的某一个长度为\(k\)的子区间全部异或上任意值,\(f(a,b)\)为使得\(a\)和\(b\)相同的最少的操作数量。支持单点修改\(a,b\),并在开头和每次修改后输出\(f(a,b)\)的值。\(n,k,q\le2\times10^5,w\le2^{14}\)。题解......
  • CF1456E XOR-ranges
    题面传送门好题。首先比较自然的,相当于按照数位DP的方法,将\([l,r]\)剖成\(k\)段,其中每一段都是最高若干位确定,底下若干位任取的形式。这样在\([l,r]\)里面选择相当于在这\(O(k)\)个区间里面选择。然后假设我们依次选择好了,考虑如何计算答案。答案显然是位独立的,对于......
  • AtCoder Beginner Contest 308 G Minimum Xor Pair Query
    洛谷传送门AtCoder传送门考虑没有删除操作怎么做。可以动态维护\(ans\),新加进来一个\(x\),我们计算\(\min\limits_{y\inS}x\oplusy\)。对\(S\)建01Trie,然后从高位往低位按位贪心,在01Trie上优先往与\(x\)这一位相同的方向走,但是前提是它的子树内有数,对于01Trie......
  • C++使用ranges库解析INI文件
    C++使用ranges库解析INI文件引言C++20引入了<ranges>头文件,C++23对其进行了完善,本文将使用该头文件提供的adaptor编写一个简单的ini解析器。ini文件格式介绍一般的ini文件由section和entry部分,比如[section]key=value;Thisisentry.section和entry均独占一行,其中sectio......
  • UVA12716 GCD等于XOR GCD XOR
    UVA12716GCD等于XORGCDXOR一道数学题。 首先,我们可以知道,a-b>=gcd(a,b)=c;其次,a-b<=axorb=c;综上,可得a-b=c,即a-b=axorb.由于范围不大,直接枚举。第一层枚举c(因为c较少),第二层枚举a,(b=a-c) 再判断c是否等于a^b即可。#include<bits/stdc++.h>usingnamespacestd;......
  • AtCoder Beginner Contest 249 G Xor Cards
    洛谷传送门AtCoder传送门好题。套路地,考虑枚举最优解的\(a\)异或和二进制下与\(k\)的\(\text{LCP}\),设在第\(i\)位不同。这样的好处是\(i\)之后的位可以随便选。之后按位贪心确定最优解\(b\)的异或和。考虑之前的答案是\(res\),当前在确定第\(j\)位,如何判断\(r......
  • AtCoder Beginner Contest 223 H Xor Query
    洛谷传送门AtCoder传送门考虑一个无脑做法:线段树维护区间线性基。时间复杂度是\(O(m\logn\log^2V)\),过于优秀以至于无法接受。事实上我们并不需要维护区间线性基,因为不带修。考虑“可持久化线性基”,开\(n\)个线性基,第\(i\)个维护前缀\([1,i]\)的数。并且插入线性......
  • The XOR Largest Pair
    #include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>usingnamespacestd;intbit[32];intn,num[5211314];structTrie{ inttrie[5211314][2],tot=1; inlinevoidInsert(inta){ ......
  • Xor-MST
    Xor-MST这道题其实是一种最小生成树算法名曰Boruvka的算法,但是平时还是Kruskal算法用的说,相信大家也是由它想起的。根据套路,由于要求的是异或边权之和的最小值,果断构建01trie。我们将样例画出来我们可以对这颗树进行dfs,可以看出两个点的LCA越深,那么它们合并代价就越......