洛谷P3300 城市规划

题意:给你一个6 * n的网格题,单点修改,询问区间联通块数。n <= 10w

解:看起来就很显然的一道题......线段树每个点用一个ufs维护连通性。完了。

我为了方便思考把图转成横着的了。

写起来真是毒瘤......

重点在于:1.建立叶节点。2.合并两个子节点。3.把新的并查集的中间两列压掉。

第一步,这个就直接枚举,merge就完事了。

第二步,把两个2列的子并查集copy到当前节点的4列的并查集上。注意右边那个并查集,fa全部要加2m,因为下标加了2m。

然后枚举中间两列merge。这样也做完了。

第三步,我们只要保留两边的两列即可。注意到有可能有两边元素的代表元在中间,我们使用左偏树技巧,切换代表元到它自己,注意vis也要变。

然后把两边的vis和facopy一份出来,用以查询代表元。

然后把前两列init,然后枚举每个元素,跟它的代表元merge。注意这一步会对连通块总数tot造成改变,最后复原即可。

最后把前两列的vis和lk从copy的那里拿来用即可。

注意,vis(当前联通块是否有建筑物)要继承代表元的,lk(能否与两边连通)直接从对应下标继承,这两个不一样!

具体实现看代码吧......

  1 #include <bits/stdc++.h>
  2 
  3 #define ck(x) ((x) == '+' || (x) == '|')
  4 
  5 const int N = 100010;
  6 
  7 template <typename T> inline void read(T &x) {
  8     x = 0;
  9     char c = getchar();
 10     while(c < '0' || c > '9') {
 11         c = getchar();
 12     }
 13     while(c >= '0' && c <= '9') {
 14         x = x * 10 + c - 48;
 15         c = getchar();
 16     }
 17     return;
 18 }
 19 
 20 int n, m, gt[24], GT, exfa[24], exvis[24], exlk[24], newvis[24], newlk[24];
 21 
 22 int exfind(int x) {
 23     return (x == exfa[x]) ? x : exfa[x] = exfind(exfa[x]);
 24 }
 25 
 26 inline int trans(int x) {
 27     return x < m ? x : x - (m << 1);
 28 }
 29 
 30 struct Node {
 31     int fa[24], tot;
 32     std::bitset<24> lk, vis;
 33     int find(int x) {
 34         return (x == fa[x]) ? x : (fa[x] = find(fa[x]));
 35     }
 36     inline void Merge(int x, int y) {
 37         x = find(x);
 38         y = find(y);
 39         if(x == y) return;
 40         fa[y] = x;
 41         tot -= (vis[x] && vis[y]);
 42         if(vis[y]) vis.set(x);
 43         return;
 44     }
 45     Node() {}
 46     Node(char *a) {
 47         tot = 0;
 48         for(register int i(0); i < m; ++i) {
 49             fa[i + m] = fa[i] = i;
 50             if(a[i] == 'O') {
 51                 vis.set(i);
 52                 vis.set(i + m);
 53                 lk.set(i);
 54                 lk.set(i + m);
 55                 ++tot;
 56             }
 57             else if(a[i] == '.') {
 58                 vis.reset(i);
 59                 vis.reset(i + m);
 60                 lk.reset(i);
 61                 lk.reset(i + m);
 62             }
 63             else if(a[i] == '-' || a[i] == '+') {
 64                 vis.reset(i);
 65                 vis.reset(i + m);
 66                 lk.set(i);
 67                 lk.set(i + m);
 68             }
 69         }
 70         for(register int i(1); i < m; ++i) {
 71             if(ck(a[i - 1]) && ck(a[i])) {
 72                 Merge(i - 1, i);
 73             }
 74             else if((ck(a[i - 1]) && a[i] == 'O') || (ck(a[i]) && a[i - 1] == 'O')) {
 75                 Merge(i - 1, i);
 76             }
 77             else if(a[i] == 'O' && a[i - 1] == 'O') {
 78                 Merge(i - 1, i);
 79             }
 80         }
 81     }
 82     inline void update() {
 83         for(register int i(0); i < m; ++i) {
 84             int t(find(i));
 85             fa[i] = fa[t] = i;
 86             vis[i] = vis[t];
 87 
 88             t = find(i + m * 3);
 89             fa[i + m * 3] = fa[t] = i + m * 3;
 90             vis[i + m * 3] = vis[t];
 91         }
 92 
 93         memcpy(exfa, fa, sizeof(fa));
 94         for(register int i(0); i < m; ++i) {
 95             exvis[i] = vis[i];
 96             exvis[i + m * 3] = vis[i + m * 3];
 97             exlk[i] = lk[i];
 98             exlk[i + m * 3] = lk[i + m * 3];
 99         }
100 
101         int temp = tot;
102         for(register int i(0); i < m; ++i) {
103             fa[i] = i;
104             fa[i + m] = i + m;
105         }
106         for(register int i(0); i < m; ++i) {
107             Merge(i, trans(exfind(i)));
108             Merge(i + m, trans(exfind(i + m * 3)));
109         }
110         for(register int i(0); i < m; ++i) {
111             vis[i] = exvis[exfind(i)];
112             vis[i + m] = exvis[exfind(i + m * 3)];
113             lk[i] = exlk[i];
114             lk[i + m] = exlk[i + m * 3];
115         }
116         tot = temp;
117         return;
118     }
119     inline Node merge(const Node &w) const {
120         Node ans;
121         /// copy
122         for(register int i(0); i < m; ++i) {
123             ans.fa[i] = fa[i];
124             ans.lk[i] = lk[i];
125             ans.vis[i] = vis[i];
126 
127             ans.fa[i + m] = fa[i + m];
128             ans.lk[i + m] = lk[i + m];
129             ans.vis[i + m] = vis[i + m];
130 
131             ans.fa[i + m * 2] = w.fa[i] + m * 2;
132             ans.lk[i + m * 2] = w.lk[i];
133             ans.vis[i + m * 2] = w.vis[i];
134 
135             ans.fa[i + m * 3] = w.fa[i + m] + m * 2;
136             ans.lk[i + m * 3] = w.lk[i + m];
137             ans.vis[i + m * 3] = w.vis[i + m];
138         }
139         ans.tot = tot + w.tot;
140         /// merge
141         for(register int i(0); i < m; ++i) {
142             if(ans.lk[i + m] && ans.lk[i + m * 2]) { /// -> <-
143                 ans.Merge(i + m, i + m * 2);
144             }
145         }
146         ans.update();
147         return ans;
148     }
149 }node[N << 2];
150 
151 char str[N][6];
152 
153 void build(int l, int r, int o) {
154     if(l == r) {
155         node[o] = Node(str[r]);
156         return;
157     }
158     int mid = (l + r) >> 1;
159     build(l, mid, o << 1);
160     build(mid + 1, r, o << 1 | 1);
161     node[o] = node[o << 1].merge(node[o << 1 | 1]);
162     return;
163 }
164 
165 void change(int p, int l, int r, int o) {
166     if(l == r) {
167         node[o] = Node(str[r]);
168         return;
169     }
170     int mid = (l + r) >> 1;
171     if(p <= mid) {
172         change(p, l, mid, o << 1);
173     }
174     else {
175         change(p, mid + 1, r, o << 1 | 1);
176     }
177     node[o] = node[o << 1].merge(node[o << 1 | 1]);
178     return;
179 }
180 
181 Node ask(int L, int R, int l, int r, int o) {
182     if(L <= l && r <= R) {
183         return node[o];
184     }
185     int mid = (l + r) >> 1;
186     if(R <= mid) {
187         return ask(L, R, l, mid, o << 1);
188     }
189     if(mid < L) {
190         return ask(L, R, mid + 1, r, o << 1 | 1);
191     }
192     Node temp(ask(L, R, l, mid, o << 1));
193     temp = temp.merge(ask(L, R, mid + 1, r, o << 1 | 1));
194     return temp;
195 }
196 
197 int main() {
198 
199     read(n); read(m);
200     for(int i = 1; i <= n; i++) {
201         scanf("%s", str[i]);
202         for(int j = 0; j < m; j++) {
203             if(str[i][j] == '-') {
204                 str[i][j] = '|';
205             }
206             else if(str[i][j] == '|') {
207                 str[i][j] = '-';
208             }
209         }
210     }
211 
212     build(1, n, 1);
213 
214     int q, x, y;
215     char ss[2];
216     read(q);
217     for(int i = 1; i <= q; i++) {
218         scanf("%s", ss); read(x); read(y);
219         if(ss[0] == 'C') { /// change
220             scanf("%s", ss);
221             if(ss[0] == '-') {
222                 ss[0] = '|';
223             }
224             else if(ss[0] == '|') {
225                 ss[0] = '-';
226             }
227             str[x][y - 1] = ss[0];
228             change(x, 1, n, 1);
229         }
230         else { /// Query
231             Node temp = ask(x, y, 1, n, 1);
232             printf("%d\n", temp.tot);
233         }
234     }
235 
236     return 0;
237 }
AC代码

这代码常数奇大...

 

转载于:https://www.cnblogs.com/huyufeifei/p/10841280.html

标题SpringBoot智能在线预约挂号系统研究AI更换标题第1章引言介绍智能在线预约挂号系统的研究背景、意义、国内外研究现状及论文创新点。1.1研究背景与意义阐述智能在线预约挂号系统对提升医疗服务效率的重要性。1.2国内外研究现状分析国内外智能在线预约挂号系统的研究与应用情况。1.3研究方法及创新点概述本文采用的技术路线、研究方法及主要创新点。第2章相关理论总结智能在线预约挂号系统相关理论,包括系统架构、开发技术等。2.1系统架构设计理论介绍系统架构设计的基本原则和常用方法。2.2SpringBoot开发框架理论阐述SpringBoot框架的特点、优势及其在系统开发中的应用。2.3数据库设计与管理理论介绍数据库设计原则、数据模型及数据库管理系统。2.4网络安全与数据保护理论讨论网络安全威胁、数据保护技术及其在系统中的应用。第3章SpringBoot智能在线预约挂号系统设计详细介绍系统的设计方案,包括功能模块划分、数据库设计等。3.1系统功能模块设计划分系统功能模块,如用户管理、挂号管理、医生排班等。3.2数据库设计与实现设计数据库表结构,确定字段类型、主键及外键关系。3.3用户界面设计设计用户友好的界面,提升用户体验。3.4系统安全设计阐述系统安全策略,包括用户认证、数据加密等。第4章系统实现与测试介绍系统的实现过程,包括编码、测试及优化等。4.1系统编码实现采用SpringBoot框架进行系统编码实现。4.2系统测试方法介绍系统测试的方法、步骤及测试用例设计。4.3系统性能测试与分析对系统进行性能测试,分析测试结果并提出优化建议。4.4系统优化与改进根据测试结果对系统进行优化和改进,提升系统性能。第5章研究结果呈现系统实现后的效果,包括功能实现、性能提升等。5.1系统功能实现效果展示系统各功能模块的实现效果,如挂号成功界面等。5.2系统性能提升效果对比优化前后的系统性能
在金融行业中,对信用风险的判断是核心环节之一,其结果对机构的信贷政策和风险控制策略有直接影响。本文将围绕如何借助机器学习方法,尤其是Sklearn工具包,建立用于判断信用状况的预测系统。文中将涵盖逻辑回归、支持向量机等常见方法,并通过实际操作流程进行说明。 一、机器学习基本概念 机器学习属于人工智能的子领域,其基本理念是通过数据自动学习规律,而非依赖人工设定规则。在信贷分析中,该技术可用于挖掘历史数据中的潜在规律,进而对未来的信用表现进行预测。 二、Sklearn工具包概述 Sklearn(Scikit-learn)是Python语言中广泛使用的机器学习模块,提供多种数据处理和建模功能。它简化了数据清洗、特征提取、模型构建、验证与优化等流程,是数据科学项目中的常用工具。 三、逻辑回归模型 逻辑回归是一种常用于分类任务的线性模型,特别适用于二类问题。在信用评估中,该模型可用于判断借款人是否可能违约。其通过逻辑函数将输出映射为0到1之间的概率值,从而表示违约的可能性。 四、支持向量机模型 支持向量机是一种用于监督学习的算法,适用于数据维度高、样本量小的情况。在信用分析中,该方法能够通过寻找最佳分割面,区分违约与非违约客户。通过选用不同核函数,可应对复杂的非线性关系,提升预测精度。 五、数据预处理步骤 在建模前,需对原始数据进行清理与转换,包括处理缺失值、识别异常点、标准化数值、筛选有效特征等。对于信用评分,常见的输入变量包括收入水平、负债比例、信用历史记录、职业稳定性等。预处理有助于减少噪声干扰,增强模型的适应性。 六、模型构建与验证 借助Sklearn,可以将数据集划分为训练集和测试集,并通过交叉验证调整参数以提升模型性能。常用评估指标包括准确率、召回率、F1值以及AUC-ROC曲线。在处理不平衡数据时,更应关注模型的召回率与特异性。 七、集成学习方法 为提升模型预测能力,可采用集成策略,如结合多个模型的预测结果。这有助于降低单一模型的偏差与方差,增强整体预测的稳定性与准确性。 综上,基于机器学习的信用评估系统可通过Sklearn中的多种算法,结合合理的数据处理与模型优化,实现对借款人信用状况的精准判断。在实际应用中,需持续调整模型以适应市场变化,保障预测结果的长期有效性。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值