分组 (并查集)
来源:互联网 发布:浙江网络作家协会主席 编辑:程序博客网 时间:2024/06/03 20:38
分组
10.23
问题可以转化为,从后往前,选择一段最长的合法区间并分割,重复进行直到完成为止。
从std中收获一种神奇的并查集写法(下面隐藏处),准备研究研究。(按秩合并优化路径压缩??还只有一个数组??看起来就很优)
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define N 150000#define LL long longusing namespace std;inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); } return x * f;}int n, idc = 0, K;int a[N], ans[N];bool vis[N], dvis[N], issqr[N * 2];int f[N * 2];int getfa(int x) { //return f[x] > 0 ? (f[x] = getfa(f[x])) : x; return f[x] == x ? x : (f[x] = getfa(f[x]));}void unionn(int u, int v) { u = getfa(u), v = getfa(v); if (u != v) { //if (f[u] > f[v]) swap(u, v); //f[u] += f[v]; f[v] = u; }}bool check(int u, int v) { int s1 = getfa(u), s2 = getfa(u + N);//反点 int t1 = getfa(v), t2 = getfa(v + N); if (s1 == t1) return 1; if (s2 == t2) return 1; unionn(s1, t2); unionn(s2, t1); return 0;}void solve1() { for (int i=n, j=n; i;) { for (bool flag=1; j; j--) { for (int k=1; k*k-a[j] < N; k++) { if (k*k-a[j] <= 0) continue; if ( vis[k*k-a[j]] ) { flag = 0; break;} } if ( !flag ) break; vis[a[j]] = 1; } if ( !j ) break; ans[++idc] = j; for ( ; i>j; i--) vis[a[i]] = 0; }}void solve2() { //memset(f, -1, sizeof f); for(int i=1; i<2*N; i++) f[i] = i; for(int i=1; i*i<2*N; i++) issqr[i*i] = 1; for(int i=n, j=n; i; ) { for( ; j; j--) { bool flag = 1; if ( vis[a[j]] ) { if ( issqr[a[j] + a[j]] ) {//当前堆内冲突 if ( dvis[a[j]] ) break;//区间内已有两个相同数字 for (int k=1; k*k-a[j]<N; k++) { if (k*k-a[j] <= 0) continue; if (vis[k*k-a[j]] && k*k != a[j]*2) { flag = 0; break; } } if ( !flag ) break; dvis[a[j]] = 1; } } else {//之前没有出现过 for (int k=1; k*k-a[j] < N; k++) { if (k*k-a[j] <= 0) continue; if ( vis[k*k-a[j]] ) {//处理并查集 if ( dvis[k*k-a[j]] || dvis[a[j]] ) { flag = 0; break;} if ( check(k*k-a[j], a[j]) ) {flag = 0; break;} } } if ( !flag ) break; vis[a[j]] = 1; } } if ( !j ) break; ans[++idc] = j; //for ( ; i>j; i--) f[a[i]] = f[a[i] + N] = -1, vis[a[i]] = 0, dvis[a[i]] = 0; for ( ; i>j; i--) f[a[i]] = a[i], f[a[i] + N] = a[i] + N, vis[a[i]] = 0, dvis[a[i]] = 0; }}int main() { freopen("division.in", "r", stdin); freopen("division.out", "w", stdout); scanf("%d%d", &n, &K); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); if (K == 1) solve1(); else solve2(); printf("%d\n", idc + 1); for(int i=idc; i; i--) printf("%d ", ans[i]); return 0;}
阅读全文
0 0
- 分组 (并查集)
- 分组并查集(种类并查集)
- 并查集(保存分组结果)
- poj 1703(并查集分组)
- luogu3940:分组(并查集)
- 分组背包+并查集
- hdu1829 A Bug's Life (分组并查集)
- A Bug's Life (分组 并查集)
- CSU 1326: The contest(并查集+分组背包)
- poj2492-并查集基于分组
- 分组背包dp+并查集 vijos1250
- 分组并查集 hdu 1829
- Codeforces Round #383 (Div. 2)D-(并查集&分组背包)|(搜索&01背包)
- poj 1703 Find them, Catch them (分组并查集 偏移向量实现)
- HDU 1829 A Bug's Life (分组并查集)
- HDOJ 题目1829A Bug's Life(分组并查集)
- hdu 1829 A Bug's Life(分组并查集)
- A Bug's Life(分组并查集 奇偶表)
- mysql 主从
- 机器学习基本概念(3)--线性模型概述
- java类库---RunTime类
- IDEA使用攻略-设置篇
- while,shift,until,case
- 分组 (并查集)
- spark程序的运行过程
- 数学知识
- C#批量修改文件名
- .NET简谈组件程序设计之(异步委托)
- Android--Notification基础介绍
- 深度学习之基础网络-SqueezeNet
- 669. Trim a Binary Search Tree
- python 匿名函数 lambda