题目

描述

题目大意

给你一个数列,接下来有许多个操作,使得区间[l1,r1][l_1,r_1][l1​,r1​]和[l2,r2][l_2,r_2][l2​,r2​]对应的位置染上同样的颜色(使得它们相同)。

最后输出9∗10颜色数−19*10^{颜色数-1}9∗10颜色数−1


思考历程

首先看到这题就自然而然地往数据结构方面想(废话!)

接着先想平衡树。既然要将这两个区间变成一样的,那就将它们各自放到子树中,然后对于两个子树的根打上标记。

接下来问题就出现了,怎么维护?怎么下传?并且由于它可能多个标记在一起,这样的时间复杂度岂不是翻天了?

然后我开始想,能不能将这些东西用同一棵子树来代替呢?

想来想去都不能,因为在后面这棵子树总是会被拆开的。

于是我又去想分块,想了一下后开始打,打了几句后突然发现——我没有办法保证这些块都是完全配对的!

想不出来,最终颓废,拿了暴力303030分的好成绩。


正解

首先有WMY的强大分块做法,我大概听懂了,不过好复杂。

我也没有打,也懒得打,何况他自己就被卡了常数。

所以这里就先不介绍了。

题解的做法是ST表。

ST表是什么东西?就是打RMQRMQRMQ时用的那个DP(数据结构?),也可以理解为倍增表。

这题的ST表做法简单易懂,令人大开眼界。

一个区间可以变成两个小区间(这两个小区间之间会有重合部分),两个小区间的并集就是这个大区间。

对于要合并的两个区间,分别这样拆一下,然后对应的合并在一起。

这和之前RMQ的道理是一样的。

(当然,实际上也可以像倍增一样搞,这样的好处是没有重合部分,但对于这题并没有什么卵用)

接下来就变成了合并对应的两个小区间。

它们各自对应着一个ST表上的节点,所以就将这两个节点合并(当然用并查集)。

接着将每个区间分别分成两份,递归下去合并。

如果它们已经合并了,那就退出。(因为它们下面小区间的点已经被合并了。)

听起来好像很暴力的样子。

但实际上ST表上的节点只有O(nlg⁡n)O(n\lg n)O(nlgn)个。

由于合并过就退出,所以合并的次数顶多为O(nlg⁡n)O(n\lg n)O(nlgn)

那这样时间复杂度就得以保证了。

总时间复杂度就是O(nlg⁡n)O(n\lg n)O(nlgn)的


总结

using namespace std;
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 100010
int n;
struct Point{//这是为了方便操作而搞出来的指针式链表(真是造福人类)
Point *p;
} st[N][17];
Point *getfa(Point &x){
if (x.p==&x)
return &x;
return x.p=getfa(*x.p);
}
inline void merge(int x,int y,int k){
Point *xx=getfa(st[x][k]),*yy=getfa(st[y][k]);
if (xx==yy)
return;
xx->p=yy;
if (!k)
return;
merge(x,y,k-1),merge(x+(1<<k-1),y+(1<<k-1),k-1);
}
inline void connect(int x,int y,int len){
int k=log2(len);
merge(x,y,k);
merge(x+len-(1<<k),y+len-(1<<k),k);
}
int main(){
int T;
scanf("%d%d",&n,&T);
for (int i=1;i<=n;++i)
for (int j=0;j<17;++j)
st[i][j].p=&st[i][j];
while (T--){
int l1,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
connect(l1,l2,r1-l1+1);
}
int cnt=0;
for (int i=1;i<=n;++i)
if (getfa(st[i][0])==&st[i][0])
cnt++;
int ans=9;
for (int i=1;i<cnt;++i)
ans=ans*10ll%1000000007;
printf("%d\n",ans);
return 0;
}

总结

我真的想不到原来ST表还可以这样用……

[JZOJ4633] 【GDOI2017模拟7.15】萌萌哒的更多相关文章

  1. [JZOJ4640] 【GDOI2017模拟7.15】妖怪

    题目 描述 题目大意 给你一堆aia_iai​和bib_ibi​(方便起见用的变量和上面不一样),让你搞出一个xxx(相当于题目中的ba\frac{b}{a}ab​,随便推推就能知道), 使得max⁡ ...

  2. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  3. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  4. NOIP模拟赛15

    NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day1 T1 天天去哪儿吃 直接枚举 #include<cstdio> #include<algorithm> using ...

  5. JZOJ.5281【NOIP2017模拟8.15】钦点

    Description

  6. noip模拟赛#15

    #15 T1:a[i]>=a[i/2].输出a的最大字典序 =>可以发现这是二叉树的情况那么就先预处理出每个点有多少个儿子然后递归处理就可以了. #include<cstdio> ...

  7. [考试反思]0809NOIP模拟测试15:解剖

    说在前面: 不建议阅读.这里没有考试经验,只有一大堆负面情绪. 看了你不会有什么收获.看完了就不要怪我影响了你的心情. 以后不粘排行榜了.没什么意思没什么用. 但是我的意思并不是因为这次没考好的一时兴 ...

  8. [NOIP2018模拟10.15]比赛报告

    闲扯 昨晚又颓到好晚,Yali的降智光环感觉持续至今... 题面好评 T1T3都玩过 逃) T1没看多久就开始写二分+并查集 然后T3看着眼熟想了一个多小时...结果啥都没想出来 赶紧看T2发现还是没 ...

  9. noi.ac NOI挑战营模拟赛1-5

    注:因为博主是个每次考试都爆零垫底的菜鸡,所以此篇博客很有可能咕咕咕 (指只贴AC代码不写题解的......如果我真的不会做的话,就不能怪我了qwqwq) Day1 T1 swap 23pts 从一个 ...

随机推荐

  1. CSS3:目录

    ylbtech-CSS3:目录 1.返回顶部 1. http://www.runoob.com/css3/css3-tutorial.html 2. 2.返回顶部   3.返回顶部   4.返回顶部 ...

  2. Git 远程仓库分支管理

    目录 目录 速查表 关联远程代码仓库 克隆远程仓库 分支管理 创建分支 切换分支 合并分支 删除分支 解决冲突 速查表 指令 作用 git branch 查看分支 git branch newBran ...

  3. iOS开发系列-iOS布局相关

    LayoutSubViews 需要在某个View调整子视图的位置时,可以重写. 以下情况会出发LayoutSubViews方法的调用 init初始化不会触发layoutSubviews,但是是用ini ...

  4. jdk1.8新特性学习

    package com.xll.code.jdk1_8study; import com.xll.code.jdk1_8study.pojo.User; import org.junit.jupite ...

  5. 安装rubygems

    转载 http://blog.csdn.net/huanghai200911/article/details/51251472 1,下载rubygems-2.4.8.tar包,下载地址:https:/ ...

  6. leetcode-421-数组中两个数的最大异或值*(前缀树)

    题目描述: 方法一: class Solution: def findMaximumXOR(self, nums: List[int]) -> int: root = TreeNode(-1) ...

  7. Java 基础 - 内存泄露Memory leak & 内存溢出Out of memory

    内存泄露 & 内存溢出 关系 https://www.cnblogs.com/panxuejun/p/5883044.html 内存泄露的6种情况: https://blog.csdn.net ...

  8. 带撤销贪心——cf1148F好题

    自己不会做,看了题解懂得 从最高位依次往低位遍历,因为偶数个1是不改变符号的,所以带个贪心即可(可以看成是带撤销的..) 每轮循环用sum记录该位选择1可以减少的值 如果是负数,就不要改成1 如果是正 ...

  9. CentOS升级GDB

    需要先安装ncurses-devel和texinfo 如果不安装ncurses-devel,编译会出错 如果不安装texinfo或者版本太低,安装会出错 1.yum install -y ncurse ...

  10. PHP 统计数组中所有的值出现的次数 array_count_values 函数

    array_count_values() 函数用于统计数组中所有的值出现的次数. array_count_values() PHP array_count_values() 函数用于统计数组中所有的值 ...