扩展域并查集
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define endl "\n"
const int N = 1e6 + 5;
int f[N], n, k, ans;
void init() { for (int i = 1; i <= 3 * n; i++) f[i] = i; }
int find(int x) { return x == f[x]?x:f[x] = find(f[x]); }
int main()
{
scanf("%d%d", &n, &k);
init();
while (k -- ) {
int c, a, b;
scanf("%d%d%d", &c, &a, &b);
if (a > n || b > n) { ans ++; continue; }
if (c == 1) {
int u = find(a), v = find(b);
if (find(a + n) != find(b) && find(a + 2 * n) != find(b)) {
if (u != v) {
f[u] = v;
if (find(a + n) != find(b + n))
f[find(a + n)] = find(b + n);
if (find(a + 2 * n) != find(b + 2 * n))
f[find(a + 2 * n)] = find(b + 2 * n);
}
}
else ans++;
}
if (c == 2) {
if (a == b) { ans++; continue; }
if (find(a) != find(b) && find(a) != find(b + n)) {
if (find(a + n) != find(b))
f[find(a + n)] = find(b);
if (find(a) != find(b + 2 * n))
f[find(a)] = find(b + 2 * n);
if (find(a + 2 * n) != find(b + n))
f[find(a + 2 * n)] = find(b + n);
}
else ans++;
}
}
printf("%d\n", ans);
return 0;
}
*带权并查集例题
* 链接:https://www.luogu.com.cn/problem/P1196
**/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3e4 + 5;
//dist[i] 节点i到上级的距离 length[i] 以i为根节点的高度
int fa[N], dist[N], length[N];
int x, y, n;
char t;
int find(int x) {
if (x == fa[x]) return x;
//求出根节点的同时更新fa[x] 到 根节点的距离
int fx = find(fa[x]);
//求出x的根节点的同时让x指向根节点 并更新dist[x] 为x到根节点的距离
dist[x] += dist[fa[x]];
//将父节点更新为根节点
return fa[x] = fx;
}
void merege(int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) return ;
//将一堆的根节点作为另一堆根节点的上级
fa[fx] = fy;
//更新作为子结点的根节点到其父节点的距离 同时更新合并后两堆的总数
dist[fx] += length[fy], length[fy] += length[fx];
}
int query(int x, int y) {
//由于不知道x和y是否直接指向根节点, 所以需要求一遍x 和 y到根节点的距离
int fx = find(x), fy = find(y);
if (fx != fy) return -1;
return abs(dist[x] - dist[y]) - 1;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= N; i ++ ) fa[i] = i, length[i] = 1;
while (n -- ) {
//cin >> t;
getchar();getchar();
scanf("%c", &t); // 如果用cin >> t; 就不需要getcahr() scanf()
scanf("%d%d", &x, &y);
if (t == 'M') merege(x, y);
else printf("%d\n", query(x, y));
}
return 0;
}
poj1163
暴力递归
if (i == n) {
MaxSum[i][j] = d[i][j];
} else {
int x = dpMaxSum(i + 1, j, n);
int y = dpMaxSum(i + 1, j + 1, n);
MaxSum[i][j] = max(x, y) + d[i][j];
}
记忆化搜索
#include <iostream>
#include <string.h>
#define MAXN 105
using namespace std;
int MaxSum[MAXN][MAXN],d[MAXN][MAXN];
int dpMaxSum(int i, int j, int n){
if(MaxSum[i][j] != -1) {
return MaxSum[i][j];
}
if(i == n){
MaxSum[i][j] = d[i][j];
}
else{
int x = dpMaxSum(i + 1, j,n);
int y = dpMaxSum(i + 1, j + 1,n);
MaxSum[i][j] = max(x,y) + d[i][j];
}
return MaxSum[i][j];
}
二维迭代
#include <iostream>
#include <string.h>
#define MAXN 105
using namespace std;
int MaxSum[MAXN][MAXN],d[MAXN][MAXN];
int dpMaxSum(int i, int j, int n){
for(int i = 1; i <= n; i++){
MaxSum[n][i] = d[n][i];
}
for(int i = n - 1; i>=1; i--){
for(int j = 1; j <= i; j++){
MaxSum[i][j] = max(MaxSum[i + 1][j],MaxSum[i + 1][j + 1]) + d[i][j];
}
}
return MaxSum[1][1];
}
一维迭代优化
#include <iostream>
#include <string.h>
#define MAXN 105
using namespace std;
int MaxSum[MAXN],d[MAXN][MAXN];
int dpMaxSum(int i, int j, int n){
for(int i = 1; i <= n; i++){
MaxSum[i] = d[n][i];
}
for(int i = n - 1; i>=1; i--){
for(int j = 1; j <= i; j++){
MaxSum[j] = max(MaxSum[j],MaxSum[j + 1]) + d[i][j];
}
}
return MaxSum[1];
}
最大子段和
ll Maxsum(int n){
ll dp = arr[0];
ll ans = 0;
ans = max(ans, dp);
for(int i = 1; i < n; i++){
if(dp >= 0){
dp += arr[i];
}
else{
dp = arr[i];
}
ans = max(dp,ans);
}
return ans;
}
矩阵连乘
#include <iostream>
using namespace std;
const int size = 105;
int m[size][size],s[size][size];
int p[size];
void Min_matrix(int n){
for(int l = 2; l <= n; l++){
for(int i = 1; i <= n - l + 1; i++){
int j = i + l - 1;
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
s[i][j] = i;
for(int k = i + 1; k < j; k++){
int temp = m[i][k] + m[k + 1][j] + p[i - 1]*p[k]*p[j];
if(m[i][j] > temp){
m[i][j] = temp;
s[i][j] = k;
}
}
}
}
}
滑雪
#include <iostream>
using namespace std;
const int maxn = 105;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const int inf = 0x7fffffff;
int g[maxn][maxn], f[maxn][maxn];
int r, c, ans = -inf;
inline bool check(int x1, int y1, int x2, int y2)
{
if (g[x1][y1] >= g[x2][y2]) return false;
if (x1 <= 0 || x1 > r || y1 <= 0 || y1 > c) return false;
return true;
}
int dfs(int i, int j)
{
if (f[i][j]) return f[i][j];
f[i][j] = 1;
for (int d = 0; d < 4; d++) {
int x = i + dx[d], y = j + dy[d];
if (!check(x, y, i, j)) continue;
f[i][j] = max(dfs(x, y) + 1, f[i][j]);
}
return f[i][j];
}
int main()
{
cin >> r >> c;
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
cin >> g[i][j];
}
}
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
ans = max(dfs(i, j), ans);
}
}
cout << ans << endl;
return 0;
}
最长上升子序列
朴素O(n^2)
int dp[MAXN],a[MAXN];
int main(){
int n;
while(cin>>n,n){
int maxx = 0;
memset(dp,1,sizeof(dp));
for(int i = 1; i <= n; i++){
cin>>a[i];
}
for(int i = 1; i <= n; i++){
for(int j = 1; j < i; j++){
if(a[i] > a[j]){
dp[i] = max(dp[j] + 1,dp[i]);
}
}
}
maxx = dp[1];
for(int i = 1; i <= n; i++){
maxx = max(maxx,dp[i]);
}
cout<<maxx<<endl;
}
return 0;
}
贪心加二分
int dp[MAXN],a[MAXN];
int Lis(int n){
int l = 1;
dp[1] = a[1];
for(int i = 2; i <= n; i++){
if(a[i] > dp[l]){
l++;
dp[l] = a[i];
}
else{
int pos = lower_bound(dp + 1,dp + l,a[i]) - dp;
dp[pos] = a[i];
}
}
return l;
}
最长公共子序列
void Lcs(char *s1, char *s2){
for(int i = 1; i <= strlen(s1); i++){
for(int j = 1; j <= strlen(s2); j++){
if(s1[i - 1] == s2[j - 1]){
dpmaxlenth[i][j] = dpmaxlenth[i - 1][j - 1] + 1;
}
else if(dpmaxlenth[i - 1][j] >= dpmaxlenth[i][j - 1]){
dpmaxlenth[i][j] = dpmaxlenth[i - 1][j];
}
else{
dpmaxlenth[i][j] = dpmaxlenth[i][j - 1];
}
}
}
}