栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【2022国赛模拟】[ZROI1778]矩阵——构造

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【2022国赛模拟】[ZROI1778]矩阵——构造

ZR省选十连测day6 矩阵 题目描述


题解

正解是刚好卡到 26 次的,说一个最多 24 次的做法。

首先考虑只要求对角线为 0 的情况,相当于要把所有 i ≠ j ineq j i​=j 的位置填上。考虑一次操作相当于一个行标和列标匹配的过程,我们可以考虑用类似CDQ分治的方法,在线段树上每次让前一半标号做行,后一半标号做列,这样可以在 2 n 2n 2n 次操作内刚好填满所有 i < j i j i>j i>j 的位置反过来做即可。

然后发现这个过程其实很浪费,可以让线段树上同一深度的操作同时做,也就是并行计算,因为我们只要 i ≠ j ineq j i​=j 嘛。这样操作次数就是 log ⁡ n log n logn 了,其本质上和二进制分组是一样的。

然后考虑这道题的情况,对角线下面还有一条 0。这其实就是把我们原来要填的 i > j i>j i>j 的下三角往下挪了一格,如果我们是原始的CDQ分治做法的话,可以简单地在做第二遍的时候把它简单重标号一下,然后判掉出界的行标即可。

但是直接沿用到并行计算上面会有漏洞,因为把区间的操作并起来的时候会出现一个列标号区间拼在一个行标号区间前面,这样填出来就不合法。

正解的解决方法是把原矩阵奇偶分类(或叫黑白染色?),然后另找他法。其实不需要的,我们可以直接把两遍操作过程穿插在一起:

注意到重标号仅仅是把行标号-1,所以上面的过程全部换成原标号是这样的:

这样显然不会填到两条线,而且其它位置全都会填满。

总共操作次数是 2 log ⁡ n 2log n 2logn,最大为 24。

代码
#include//JZM yyds!!
#define ll long long//God JZM!!
#define lll __int128//JZM RollInDark!!
#define uns unsigned
#define fi first
#define se second
#define IF (it->fi)
#define IS (it->se)
#define lowbit(x) ((x)&-(x))
#define END putchar('n')
#define inline jzmyyds
using namespace std;
const int MAXN=3005;
const ll INF=1e16;
ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();
	return f?x:-x;
}
int ptf[50],lpt;
void print(ll x,char c='n'){
	if(x<0)putchar('-'),x=-x;
	ptf[lpt=1]=x%10;
	while(x>9)x/=10,ptf[++lpt]=x%10;
	while(lpt)putchar(ptf[lpt--]^48);
	if(c>0)putchar(c);
}
int n,tot,Q;
#define pii pair
vectorT,F;
struct step{setr,c;};
vectoras;
int main()
{
	n=read(),Q=read();
	T.emplace_back(pii(1,n));
	while(!T.empty()){
		for(int o=0,e;o<2;o++){
			e=o,as.resize(as.size()+1);
			auto&st=as.back();
			for(auto&lr:T){
				int l=lr.fi,r=lr.se,mid=(l+r)>>1;
				if(e^=1){
					for(int i=l;i<=mid;i++)st.r.insert(i);
					for(int i=mid+1;i<=r;i++)st.c.insert(i);
				}else{
					for(int i=l;i<=mid;i++)st.c.insert(i);
					for(int i=mid+1;i<=r;i++)if(i
			int l=lr.fi,r=lr.se,mid=(l+r)>>1;
			if(mid>l)F.emplace_back(pii(l,mid));
			if(r>mid+1)F.emplace_back(pii(mid+1,r));
		}T.swap(F);
	}
	print(as.size());
	for(auto&x:as){
		print(x.r.size(),' '),print(x.c.size(),0);
		for(int z:x.r)printf(" %d",z);
		for(int z:x.c)printf(" %d",z);
		END;
	}
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/935280.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号