首页 > 编程语言 >编程入门题瞎做(一)

编程入门题瞎做(一)

时间:2022-08-14 14:33:51浏览次数:76  
标签:const 入门 int void 编程 fa UFST include

luogu P3295 [SCOI2016]萌萌哒

题目链接

这里的计数没有任何的技术含量,当你知道那几个位置必须一样后,就疯狂乘 \(10\) 就可以了。

现在问题是怎么找到那几个位置必须一样。
考虑一种最暴力的方法,对于任意 \(i\ (0\leq i\leq r_1-l_1+1)\) 我们把 \(i+l_1\) 和 \(i+l_2\) 用并查集并起来。
最后显然一个集合内的位置都是相同的颜色。这样做的时间复杂度是 \(O(n^2\log n)\) 。

考虑怎么优化,想到之前学的线段树优化建图,发现不需要进行实时修改,直接用 \(\tt ST\) 表就可以了。
我们定义 \(fa(i,j)\) 表示 \([i,i+2^j-1]\) 这段区间内的根 的左端点。
也就是说我们把并查集做一个类似倍增的方法,它的父亲对应的也是一段区间,为了方便我们钦定它的父亲为根的左端点。
合并的话跟倍增几乎时一模一样。

注意到最后要把所有的相同位置拉入到一个集合,也就是对于每一层,都要和它的上一层合并。
具体的可以看一下代码。

点击查看代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)

const int N = 1e5 + 5;
const int mod = 1e9 + 7;

int n, m, lg[N];

namespace UFST {
int fa[N][20];
inline int find(int x, int k);
inline void merge(int a, int b, int k);
}
using UFST::fa;

signed main(void) { 
  read(n, m);
  for (int i = 1, l1, l2, r1, r2; i <= m; i++) {
    read(l1, r1, l2, r2);
    node[i] = Node(l1, r1, l2, r2);
  }
  for (int i = 1; i <= n; i++)
    for (int j = 0; j <= 20; j ++) fa[i][j] = i;
  for (int i = 1, l1, r1, l2, r2; i <= m; i++) {
    l1 = node[i].l1, r1 = node[i].r1, l2 = node[i].l2, r2 = node[i].r2;
    for (int j = 20; j >= 0; j --) 
      if (l1 + (1 << j) - 1 <= r1) {
        UFST::merge(l1, l2, j);
        l1 += 1 << j; l2 += 1 << j;
      }
  }
  for (int j = 20; j >= 1; j--) {
    for (int i = 1; i + (1 << j) - 1 <= n; i++) {
      int pos = UFST::find(i, j);
      UFST::merge(i, pos, j - 1);
      UFST::merge(i + (1 << j - 1), pos + (1 << j - 1), j - 1);
    }
  }
  int ans = 0;
  for (int i = 1; i <= n; i++)
    if (fa[i][0] == i) {
      if (ans == 0) ans = 9;
      else ans = 1ll * ans * 10 % mod;
    }
  std::cout << ans << std::endl;
  return 0;
}

namespace UFST {
inline int find(int x, int k) {
  if (fa[x][k] == x) return x;
  return fa[x][k] = find(fa[x][k], k);
}
inline void merge(int a, int b, int k) {
  a = find(a, k); b = find(b, k);
  if (a == b) return ;
  fa[a][k] = b;
}
}

标签:const,入门,int,void,编程,fa,UFST,include
From: https://www.cnblogs.com/Oier-GGG/p/16585241.html

相关文章

  • 第7章 函数——C++的编程模块
    第7章函数——C++的编程模块7.8编程练习题第1题#include<iostream>usingnamespacestd;//编写一个程序,不断要求用户输入两个数,直到其中的一个为0.//对于两......
  • Shell 从入门到精通 (四)条件判断
    1.基本语法[condition](注意condition前后要有空格)注意:条件非空即为true,[atguigu]返回true,[]返回false。2.常用判断条件(1)两个整数之间比较=字符串比较-lt小......
  • MapReduce入门实战
    MapReduce思想MapReduce是Google提出的一个软件架构,用于大规模数据集的并行运算。概率“Map(映射)”和“Reduce(归约)”以及它们的思想都是从函数式编程语言借鉴的,还有......
  • hadoop入门之虚拟机安装
    今天按照黑马的视频和课程资料安装了三台Centos的linux虚拟机,步骤非常简单但是视频提示会有很多踩坑的点,我就比较顺利从VMware安装到激活,网络的配置以及虚拟机的安装都非常......
  • Makefile入门
    1.Makefile引入简单编译C文件时一般用的gcc:gcc-otesta.cb.c。但是当项目变得十分庞大时,逐个文件编译,效率极低。这时候必须引入Makefile作为编译管理。当项目设计诸......
  • Shell编程
    变量:类型只有数字、字符串、数组,不用分号#!/bin/shstr_name="jack"#变量赋值,等号俩边不能有空格,比如str_name="jack"、str_name="jack"echo$str_nameecho${str_n......
  • MyBatisPlus(一、快速入门)
    1、简介  MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus可以不需要写SQL语句就能快速完......
  • C#并发编程-4 同步
    如果程序用到了并发技术,那就要特别留意这种情况:一段代码需要修改数据,同时其他代码需要访问同一个数据。这种情况就需要考虑同步地访问数据。如果下面三个条件都满足,就必......
  • 层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP
    Golang使用包(package)这种概念元素来统筹代码,所有代码功能上的可调用性都定义在包这个级别,如果我们需要调用依赖,那就“导包”就行了,无论是内部的还是外部的,使用import关键......
  • C语言指针的使用运算与数组相关编程实例
    指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。本......