2023牛客多校第三场

2023牛客多校第三场

B 很烦的dp

f[2][300][300][300]
需要前缀和优化+滚动数组

f[i][x][y][k]

D 扩展域并查集之种类并查集的最小代价

1 到 n表示行变
n+1~ 2n表示行不变
2n+1~ 3n表示列变
3n+1~ 4n表示列不变
对于一个需要变换的点比如说solve(int op)函数中a[i][j]!=op的话就需要变
那么一定是行变列不变,或者行不变列变(总之要奇数次变换)
如果不需要变的话,那么就是行不变列不变或者行变列变(总之要偶数次变换)
把决策的方案合并起来,最终一定是变不能和不变在一个并查集里面,否则return -1
然后对于行变,代价是1,列变,代价也是1,我们用
m p [ f i n d ( i ) ] + + ( 1 < = i < = n 和 2 n + 1 < = i < = 2 n ) mp[find(i)]++(1<=i<=n 和 2n+1<=i<=2n) mp[find(i)]++(1<=i<=n2n+1<=i<=2n)
然后
f o r ( a u t o [ x , y ] : m p ) a n s = m i n ( a n s , y ) for(auto [x,y]:mp)ans=min(ans,y) for(auto[x,y]:mp)ans=min(ans,y)
这道题还可以扩展,比如说每一行变换的代价是a[i],不变的代价是b[i],列变的代价是c[i],列不变的代价是d[i],求全0或者全1的最小代价
我认为这道题是一道很好的题

#include<bits/stdc++.h>
using namespace std;const int N=2020;
int p[N*4],n,a[N][N];int find(int x){if(p[x]==x)return x;return p[x]=find(p[x]);
}
//行 (1 n) (n+1 2n) 
//列 2n+1 3n 3n+1 4n
int same(int i,int j){return find(i)==find(j);
}
void merge(int i,int j){p[find(i)]=find(j);
}
int sz[N*4];
int solve(int op){for(int i=1;i<=n*4;i++)p[i]=i,sz[i]=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){int x=a[i][j]^op;if(x==1){//如果 要改 结果(行不改列不改) 或者 (行改列改)就不行if(same(i,j+2*n)||same(i+n,j+3*n))return 1e9;merge(i,j+3*n);merge(i+n,j+2*n);}else{if(same(i,j+3*n)||same(i+n,j+2*n))return 1e9;merge(i,j+2*n);merge(i+n,j+3*n);}}}
//     for(int i=1;i<=n;i++){
//         if(same(i,i+n))return 1e9;
//         int j=i+2*n;
//         if(same(j,j+n))return 1e9;
//     }map<int,int>mp;for(int i=1;i<=n;i++)mp[find(i)]++;for(int i=2*n+1;i<=3*n;i++)mp[find(i)]++;int ans=1e9;for(auto [x,y]:mp)ans=min(ans,y);return ans;
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){char c;cin>>c;if(c=='1')a[i][j]=1;}int ans=min(solve(0),solve(1));if(ans==1e9)ans=-1;cout<<ans;
}

G 二维马拉车+二维哈希

二维哈希+二分勉强能冲过去

#include <bits/stdc++.h>#define el '\n'
using namespace std;
typedef long long ll;
const int N = 2010;
const ll X = 149, Y = 941;int n, m;
int p[N];
ll px[N], py[N];
ll h1[N][N], h2[N][N];
char s[N][N];int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i) scanf("%s", s[i] + 1);px[0] = 1;for (int i = 1; i <= n; ++i) px[i] = px[i - 1] * X;py[0] = 1;for (int i = 1; i <= m; ++i) py[i] = py[i - 1] * Y;for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) {h1[i][j] = h1[i - 1][j] * X + h1[i][j - 1] * Y - h1[i - 1][j - 1] * X * Y + s[i][j];h2[i][j] = h2[i - 1][j] * X + h2[i][j - 1] * Y - h2[i - 1][j - 1] * X * Y + s[n - i + 1][m - j + 1];}auto get = [&](ll h[][N], int x1, int x2, int y1, int y2) {--x1, --y1;ll X = px[x2 - x1], Y = py[y2 - y1];return h[x2][y2] - h[x2][y1] * Y - h[x1][y2] * X + h[x1][y1] * X * Y;};ll ans = 0;for (int i = 1; i <= n; ++i) {int mr = 0, mid;for (int j = 1; j <= m; ++j) {if (j < mr) p[j] = min(p[mid * 2 - j], mr - j);else p[j] = 1;while (1) {int x1 = i - p[j], x2 = i + p[j];int y1 = j - p[j], y2 = j + p[j];if (x2 > n || x1 <= 0 || y2 > m || y1 <= 0) break;if (get(h1, x1, i, y1, y2) != get(h2, n + 1 - x2, n + 1 - i, m + 1 - y2, m + 1 - y1)) break;++p[j];}if (j + p[j] > mr) mr = j + p[j], mid = j;ans += p[j];}}for (int i = 1; i < n; ++i) {int mr = 0, mid;for (int j = 1; j < m; ++j) {if (j < mr) p[j] = min(p[mid * 2 - j], mr - j);else p[j] = 1;while (1) {int x1 = i - p[j] + 1, x2 = i + p[j];int y1 = j - p[j] + 1, y2 = j + p[j];if (x2 > n || x1 <= 0 || y2 > m || y1 <= 0) break;if (get(h1, x1, i, y1, y2) != get(h2, n + 1 - x2, n - i, m + 1 - y2, m + 1 - y1)) break;++p[j];}if (j + p[j] > mr) mr = j + p[j], mid = j;ans += p[j] - 1;}}printf("%lld\n", ans);
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char num[2001][2001];
ll h[2001][2001];
ll H[2001][2001];
ll px[2001]={1},py[2001]={1};
const int X=1145,Y=141981;
const int mod=998244353;
int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%s",num[i]+1);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){h[i][j]=((h[i-1][j]*X+h[i][j-1]*Y-h[i-1][j-1]*X*Y+num[i][j])%mod+mod)%mod;H[i][j]=((H[i-1][j]*X+H[i][j-1]*Y-H[i-1][j-1]*X*Y+num[n-i+1][m-j+1])%mod+mod)%mod;}for(int i=1;i<=2000;i++){px[i]=px[i-1]*X%mod;py[i]=py[i-1]*Y%mod;}function<bool(int,int,int,int)>check=[&](int x,int y,int a,int b){ll mid=h[x][y]-h[a-1][y]*px[x-a+1]-h[x][b-1]*py[y-b+1]+h[a-1][b-1]*px[x-a+1]%mod*py[y-b+1];x=n-x+1;y=m-y+1;a=n-a+1;b=m-b+1;swap(x,a);swap(y,b);mid-=H[x][y]-H[a-1][y]*px[x-a+1]-H[x][b-1]*py[y-b+1]+H[a-1][b-1]*px[x-a+1]%mod*py[y-b+1];return !(mid%mod);};ll ans=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int l=0,r=min({n-i,m-j,i-1,j-1});while(l<r){int mid=l+r+1>>1;if(check(i+mid,j+mid,i-mid,j-mid))l=mid;else r=mid-1;}ans+=l+1;if(i>1&&j>1){if(!check(i,j,i-1,j-1))continue;l=0,r=min({n-i,m-j,i-2,j-2});while(l<r){int mid=l+r+1>>1;if(check(i+mid,j+mid,i-1-mid,j-1-mid))l=mid;else r=mid-1;}ans+=l+1;}}printf("%lld",ans);
}

I 倍增

学习倍增的另一种用法
jmp[x][i]表示从x点变换2的i次方所能达到的最高节点
U[x][i]表示从x点以颜色i不用变换所能达到的最高节点,递推,父亲更新儿子

核心函数jump(int &x,int y)
从x点跳到低于y的代价是多少for(i=20 ~ i)ans+=1<<i
然后如果能到y,一定是不需要变换颜色的
还剩最后一步合并同类块,也就是说x跳到z,y也跳到z了,判断是否能用同一种颜色,这个时候就枚举i=0~ 60判断是否能同时有x用颜色i跳过最近公共祖先z且有y用颜色i跳过最近公共祖先z,如果没有的话ans就需要+1, ans就是 跳跃步数dep[x]+dep[y]-2*dep[z] + 变换次数(jump)

#include<bits/stdc++.h>
// #define int long long
using namespace std;
const int N=5e5+10;
int n,q,f[N][21],U[N][60],jmp[N][21],dep[N],ans;
long long a[N];
vector<int>g[N];
void dfs(int u,int fa=0){f[u][0]=fa;dep[u]=dep[fa]+1;int up=-1;for(int i=0;i<60;i++){U[u][i]=U[fa][i];if( (a[u]>>i&1)&&U[u][i]==-1)U[u][i]=u;if(~a[u]>>i&1)U[u][i]=-1;int j=U[u][i];if(up==-1|| (j!=-1&&dep[up]>dep[j]) )up=j;}jmp[u][0]=up;for(int i=1;i<=20;i++){f[u][i]=f[f[u][i-1]][i-1];if(jmp[u][i-1]!=-1)jmp[u][i]=jmp[jmp[u][i-1]][i-1];}for(auto j:g[u]){if(j==fa)continue;dfs(j,u);}
}
int lca(int x,int y){if(x==y)return x;if(dep[x]<dep[y])swap(x,y);for(int i=20;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];if(x==y)return x;for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
void jump(int &x,int y){//x->y 上跳,同时记录ans的代价for(int i=20;i>=0;i--)if(jmp[x][i]!=-1&&dep[jmp[x][i]]>dep[y])x=jmp[x][i],ans+=1<<i;
}
int so(){int x,y;cin>>x>>y;if(x==y)return 0;int z=lca(x,y);ans=dep[x]+dep[y]-2*dep[z];if(dep[x]<dep[y])swap(x,y);if(y==z){jump(x,y);int fa=f[x][0];if(a[x]&a[fa])return ans;else return -1;}jump(x,z),jump(y,z);if(jmp[x][0]==-1||jmp[y][0]==-1)return -1;if(dep[jmp[x][0]]>dep[z]||dep[jmp[y][0]]>dep[z])return -1;int need=1;for(int i=0;i<60;i++){if(U[x][i]==-1||U[y][i]==-1)continue;if(dep[U[x][i]]>dep[z]||dep[U[y][i]]>dep[z])continue;need=0;break;}return ans+need;
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);memset(U,-1,sizeof U);memset(jmp,-1,sizeof jmp);cin>>n>>q;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1,a,b;i<n;i++){cin>>a>>b,g[a].push_back(b),g[b].push_back(a);}dfs(1);while(q--)cout<<so()<<'\n';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全/信息安全—学习笔记

一、网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

归并排序(c++题解)

题目描述 将读入的 N 个数从小到大排序后输出。 输入格式 第一行为一个正整数 N。 第二行包含 N 个空格隔开的正整数 ai​&#xff0c;为你需要进行排序的数。 输出格式 将给定的 N 个数从小到大输出&#xff0c;数之间空格隔开&#xff0c;行末换行且无空格。 输入输出…

MySQL 的解析器以及 MySQL8.0 做出的改进 | StoneDB技术分享 #2

设计&#xff1a;小艾 审核&#xff1a;丁奇 编辑&#xff1a;宇亭 作者&#xff1a;柳湛宇&#xff08;花名&#xff1a;乌淄&#xff09; 浙江大学-软件工程-在读硕士、StoneDB 内核研发实习生 一、MySQL 的解析器 MySQL 所使用的解析器&#xff08;即 Lexer 和 Parser …

【Git】git reset 版本回退 git rm

前言 在日常开发时&#xff0c;我们经常会需要撤销之前的一些修改内容或者回退到之前的某一个版本&#xff0c;这时候reset命令就派上用场了 git reset 用法1——所有文件回退到某个版本 1、使用git reflog查看要回退的commit对象 2、使用git reset [-- hard/soft /mixed] …

算法通关村第二关——反转链表白银笔记

文章目录 1.链表指定区间翻转2.两两交换链表中的节点 1.链表指定区间翻转 LeetCode 92.反转链表 解法一&#xff1a;头插法。利用虚拟节点进行反转&#xff0c;因为头节点有可能发生变化&#xff0c;比如 left1 那么需要 dummyNode.next 记录头结点&#xff0c;使用虚拟头节点…

Arcgis通过模型构建器计算几何坐标

模型 模型中&#xff0c;先添加字段&#xff0c;再计算字段 计算字段 模型的计算字段中&#xff0c;表达式是类似这样写的&#xff0c;其中Xmin表示X坐标&#xff0c;Ymin表示Y坐标 !Shape.extent.Xmin!类似计算面积 !shape.area!

突破游戏行业天花板,“技术外溢”成趋势

文 | 螳螂观察 作者 | 余一 受游戏版号发放的“放缓”、人口结构的调整&#xff0c;过去两年国内游戏行业过得并不算好。前不久据相关机构发布的数据显示&#xff0c;2022年中国游戏市场实际销售收入2658.84亿元&#xff0c;同比减少306.29亿元&#xff0c;下降10.33%。且游戏…

创建个人博客(在文章的列表页,根据文章标题和文章内容实现搜索)

1. 在视图文件增加搜索表单&#xff1a; 在文章列表页的视图文件中&#xff0c;增加一个搜索表单&#xff0c;包含一个文本搜索框和一个提交按钮 <% form_tag articles_path, method: :get do %><% text_field_tag :title, params[:title], placeholder: "搜索…

海康视频插件VideoWebPlugin在vue中的实现

一,将js文件放在public文件下 二,在index中全局引入 三.在视频页面写方法,创建实例,初始化,我写的是1*4屏的 <template><!--视频窗口展示--><div idplayWnd classNameplayWnd refplayWnd styleleft: 0; bottom: 0;height: 902px;width: 60vw></div>&…

研究生阶段球形机器人水面运动部分研发项目总结文档

出现的问题 研发问题 存在闭门造车现象。闭门造车的特点就是每一步都是创新&#xff0c;但是这样的创新是没有意义的&#xff0c;因为实际上已经有人做出来了。闭门造车的后果&#xff0c;一是不管是否自己的尝试“如愿以偿”&#xff0c;都会耗费大量时间&#xff1b;二是由…

Spring JPA 实现动态SQL查询及分页

1.在持久层Service中创建EntityManager对象&#xff1b;PersistenceContext private EntityManager entityManager; 2.根据动态sql查询条目数/*** get total.*/ public Object getResultTotalBySql(String sql) {Query query entityManager.createNativeQuery(sql);return que…

Eureka 学习笔记2:EurekaClient

版本 awsVersion ‘1.11.277’ EurekaClient 接口实现了 LookupService 接口&#xff0c;拥有唯一的实现类 DiscoveryClient 类。 LookupService 接口提供以下功能&#xff1a; 获取注册表根据应用名称获取应用根据实例 id 获取实例信息 public interface LookupService<…

HTTP杂谈之Referer和Origin请求头再探

一 关于Referer和Origin的汇总 1) 知识是凌乱的,各位看官看个热闹即可2) 内容不断更新1、理解有盲区,需要及时纠正2、内容交叉有重复,需要适当删减3、扩展视野3) 以下内容都与Referer和Origin请求头有关联 nginx防盗链 HTTP杂谈之Referrer-Policy响应头 iframe标签referre…

物联网|可变参数的使用技巧|不一样的点灯实验|访问外设的寄存器|操作寄存器实现点灯|硬件编程的基本流程-学习笔记(11)

文章目录 可变参数的使用技巧第三阶段-初级实验Lesson5:不一样的点灯实验---学习I/O的输出 ☆点灯的电路图分析1 一起看看点灯的电路图Tip1:另一种点灯的电路Tip1:如何访问外设的寄存器2 STM32F407中操作GPIO的方法 通过直接操作寄存器实现点灯实验Tip1:硬件编程的基本流程 2代…

HTML5+CSS3小实例:带标题的3D多米诺人物卡片

实例:带标题的3D多米诺人物卡片 技术栈:HTML+CSS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content…

【3】C++实现多进程、多线程

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、同步与互斥1、【thread】同步并发的方法(1)创建、终止、等待、分离线程的方法1.创建线程形式1:使用一个循环执行的函数创建一个线程形式2:…

【信号去噪】基于马氏距离和EDF统计(IEE-TSP)的基于小波的多元信号去噪方法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Linux 终端生成二维码

1、安装qrencode [rootnode1 script]# yum -y install qrencode2、输出正常的 [rootnode1 aihuidi]# echo https://blog.csdn.net/weixin_43822878?t1|qrencode -o - -t utf83、输出彩色的 [rootnode1 aihuidi]# qrencode -t utf8 -s 1 https://blog.csdn.net/weixin_4382…

bash shell 杂记(4)-shell常用的几种逻辑判断与运算

严格意义上讲,本章没有多少新意,都是一些经常使用的东西,写这些的目的是记录以下,想用而想不起来的时候可以在这里找找看。 常用算数运算 我们一般使用两种方式 let 和 $(()) count=1 forlinx@ubuntu:~/test$ max=2 forlinx@ubuntu:~/test$ count=$((count+5+max*2)) fo…

Ubuntu 22.04 LTS 安装nvidia-docker NVIDIA Container Toolkit

安装docker sudo apt install docker.io docker info yeqiangyeqiang-MS-7B23:~$ sudo docker info Client:Context: defaultDebug Mode: falseServer:Containers: 12Running: 0Paused: 0Stopped: 12Images: 67Server Version: 20.10.21Storage Driver: overlay2Backing …