当前位置: 首页 > news >正文

[Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)

4722: 由乃


 

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 360  Solved: 131
[Submit][Status][Discuss]

Description


 

由于一周目的由乃穿越到了三周目,并带来了巨大的影响,改变了三周目所有未来日记所有者的命运所以三周目的
神Deus准备不利用未来日记来决定把神的位置交给谁Deus特别崇拜某知名社会主义国家领导人,因为他的寿命比神
还长,所以他想钦定下一个卡密,而不通过选举他决定钦定三周目的由乃成为卡密,去和一周目的雪辉重逢(终于
做了一件好事了)但是,既然是钦定,那么肯定还是要做做样子的,以防某些来自香港的记者造个大新闻,导致被
批判一番所以Deus决定,出一道OI题来考察由乃有没有当神的能力如果你没有看过这个番,以上内容可以无视
 
给一个长为n的序列a,每个数在0到v - 1之间,有m次操作。
操作1:每次询问一个区间中是否可以选出两个下标的集合X,Y,满足:
1.X和Y没有交集
2.设集合X中有一个元素是i,则其对集合X的贡献是a[i] + 1,要求集合X的元素的总贡献和集合Y的元素的总贡献
相等如果可以选出这两个集合,输出 Yuno否则输出 Yuki
操作2:修改一个区间l,r之间的数,使得所有l <= i <= r,a[i] = a[i] * a[i] * a[i] % v ,即区间立方
 
如果你没有看过这个番,或者你已经是国家队队员,以下内容可以无视
可以去和雪辉重逢,由乃肯定非常高兴然而可爱的由乃虽然很机智但是并不会OI呀,特别不会数据结构这种神奇的
东西(会数据结构和成为卡密有什么关系吗233333)所以她请您——未来的国家队队员来帮助她啦

 

Input


 

第一行三个数n , m , v,意义如题所述
之后一行n个数,表示序列a
之后m行每行三个数opt , l , r,表示操作类型是1还是2,操作的区间是[l , r]

 

Output


 

m行,每行一个字符串 Yuno 或者 Yuki 表示能否选出这两个集合

 

Sample Input


 

20 20 152
3 26 133 54 79 81 72 109 66 91 82 100 35 23 104 17 51 114 12 58
2 1 17
2 6 12
1 1 12
2 3 5
2 11 11
2 7 19
2 6 15
1 5 12
1 1 9
1 10 19
2 3 19
2 6 20
2 1 13
2 1 15
2 1 9
1 1 1
2 1 7
2 7 19
2 6 19
2 3 6

 

Sample Output


 

Yuno
Yuno
Yuno
Yuno
Yuki

 

HINT 


 


对于100%的数据,n , m <= 100000 , v <= 1000,数据没有梯度

 

分析:

 


 

 (话说这道题是道卡常题啊!!)

  对于数据没有梯度这种东西,还是持有吐槽的态度的……还有常数太大,还好数据水。

  好了,先说个题外话:当一个幼儿园有367个小朋友,那么肯定有两个人的生日会在同一天。

  为什么要说这个呢?

  因为这道题比如我们查询的区间长度为len,那么子区间方案数为2 ^ len,区间值域又为[len,(v + 1) * len],只要使2 ^ len >(v + 1) * len,就一定存在有解的情况(原因如上述题外话)。

  解方程:2 ^ len >(v + 1) * len ,解得len最小为 14.

  所以只要查询区间长度 len > 13 就一定有解。

  那么再来看看区间长度 <= 13的。题目让在大区间内,选两个互不相交的子集相等,可以转换成在大区间里每个数的系数有的为1(选入X集合),有的为0(不选),有的为 -1(选入Y集合);

  问是否存在使所有数加起来为0; 因为 2 ^ len 暴力枚举方案 len 是最大为13的,再乘上 m 显然时间是不够的。

  我们可以采用二分的思想,先处理完[l,mid]区间。再处理[mid + 1,r]区间,这样 2 ^ 13被划为了 2 * (3 ^ 7),显然降低了很多。但常数还是巨大的(还好数据水)。

  这样就处理完第一种查询了。

  再来看第二种修改。

  我们发现如果每次去乘常数也是巨大的,所以我们会联想到采用lazy标记。但是每次我们只询问叶子结点的值是多少,所以我们只用在询问叶子结点时才释放lazy标记。

  再来看看具体操作 a[i] = (a[i]³)^ lazy,我们是不可能暴力去乘的,常数也是巨大的。貌似快速幂也常数大了点(因为调用了乘法,取模)。

  我们发现无论再怎么次方,数都是在v以内的。我们可以预先处理出(0 ~ v - 1)的幂的表,这样每次就不用手动去乘了。

  处理这个表类似于倍增的思想,我们知道每个数的data[i][j - 1](表示i 的 2 ^ j - 1方的数是多少),就可以通过data[i][j] = data[data[i][j - 1]][j - 1]; 推出data[i][j]。O(nlogn)的预处理。

  这样每次下方lazy标记变成了严格的log,而不是像快速幂一样在log上带上大常数。

  然后操作一遍就可以了。

  二分处理:


 

  因为某G姓男子不懂二分这一块,我只好单独提出来解释一下:

  比如说有13个数区间为[2,14],mid 为 8,那么我们会分开处理[2,8]和[9,14]两段区间。

  用dfs,枚举有的数系数为1,有的数系数为0,有的数系数为-1。比如说在[2,8],[9,14]这些区间里就有数加减得0,我们是可以输出Yuno的。

  没有的话看[2,8]里面出出现过的数是否[9,14]里面也出现过,出现过也可以输出Yuno。

  话说某人问题是比如有5个数,999 3 7 4 16。如果我们会去处理[1,3]和[4,5]这两段区间,可是我们的X 和 Y集合是[2,4] 和[5],[2,4]是跨越了mid的。是不会找到的。

  我们这样想,如果在处理右区间[4,5]时,我们给[4]这里的数系数赋为-1,是不是就相当于加进了X集合。所以二分是可以处理的

 AC代码:

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cstdlib>
using namespace std;
const int V = 1e3 + 10;
const int N = 1e5 + 12;
int read()
{
    int ans = 0,f = 1;
    char i = getchar();
    while(i < '0' || i > '9'){if(i == '-')f = -1;i = getchar();}
    while(i >= '0' && i <= '9'){ans = ans * 10 + i - '0';i = getchar();}
    return ans * f;
}
int n,m,v,mid,ol,x,y,d;
int data[V][22],a[N],stack[N],cnt;
int sum[N << 2],lazy[N << 2];
bool flag[N];
void down(int rt){
    lazy[rt << 1] += lazy[rt];
    lazy[rt << 1 | 1] += lazy[rt];
    lazy[rt] = 0;
}
void push(int &ans,int &r){
    int j = 20;
    while(j >= 0){
        if(r >= (1 << j)){
           ans = data[ans][j];
           r -= (1 << j);
           if(r == 0)return;
        }
        j--;
    }
}
void updata(int L,int R,int l,int r,int rt){
    if(L <= l && r <= R){
        lazy[rt]++;
        return;
    }
    if(lazy[rt])down(rt);
    int mid = (l + r) >> 1;
    if(L <= mid)updata(L,R,l,mid,rt << 1);
    if(R >  mid)updata(L,R,mid + 1,r,rt << 1 | 1);
    return;
}
void Query(int L,int l,int r,int rt){
    if(l == r){
        push(a[L],lazy[rt]);
        return;
    }
    if(lazy[rt])down(rt);
    int mid = (l + r) >> 1;
    if(L <= mid)Query(L,l,mid,rt << 1);
    else Query(L,mid + 1,r,rt << 1 | 1);
    return;
}
void init(){
    for(int i = 0;i < v;i++){
        data[i][0] = (i * i % v) * i % v;
    }
    for(int j = 1;j <= 20;j++){
        for(int i = 0;i < v;i++){
           data[i][j] = data[data[i][j - 1]][j - 1];
        }    
    }
}
void dfsl(int u,int dis,bool k){
    if(ol)return;
    if(u == mid + 1){
        if(k){
            if(!dis){
                ol = true;
            }else if(dis >= 0 && !flag[dis]){flag[dis] = true;stack[++cnt] = dis;}
        }
        return;
    }
    dfsl(u + 1,dis,k);
    dfsl(u + 1,dis + a[u] + 1,true);
    dfsl(u + 1,dis - a[u] - 1,true);
    return;
}
void dfsr(int u,int dis,bool k){
    if(ol)return;
    if(u == y + 1){
        if(k){
            if(!dis){
                ol = true;
            }else if(dis >= 0 && flag[dis]){
                ol = true;
            }
        }
        return;
    }
    dfsr(u + 1,dis,k);
    dfsr(u + 1,dis + a[u] + 1,true);
    dfsr(u + 1,dis - a[u] - 1,true);
    return;
}
int main(){
  n = read(),m = read(),v = read();
  for(int i = 1;i <= n;i++){
       a[i] = read();
  }
  init();
  for(int i = 1;i <= m;i++){
      d = read(),x = read(),y = read();
      if(d == 2){
          updata(x,y,1,n,1);
      }else {
          if(y - x >= 13){
              puts("Yuno");
          }else {
            for(int j = x;j <= y;j++){
                Query(j,1,n,1);
            }
            mid = (x + y) >> 1;
            ol = false;cnt = 0;
            dfsl(x,0,false);
            dfsr(mid + 1,0,false);
            for(int i = 1;i <= cnt;i++){
                flag[stack[i]] = false;
            }
            if(ol)puts("Yuno");else puts("Yuki");
         }
      }
  }
  return 0;
}

 

 

    

  

转载于:https://www.cnblogs.com/lzdhydzzh/p/7657721.html

相关文章:

  • JAVA-JSP内置对象之request对象的其他方法
  • SVN冲突解决
  • JavaScript table动态生成数据
  • python-爬虫day1
  • 调用自定义验证码出现的问题
  • 程序媛,坚持这几个好习惯让你越来越美
  • 从零开始学习springBoot3(自定义json解析框架)
  • unity ugui图片自适应文字内容大小
  • Maven学习总结(四)——Maven核心概念
  • linux 命令cp拷贝
  • 屏蔽干扰CSS
  • [原]【开源框架】Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发,欢迎各位......
  • 前端(各种demo)三:优惠券,热区,等模块的实现(css方式)
  • 愤怒的TryCatch
  • asp.net core2.0网站的环境搭建和网站部署
  • 收藏网友的 源程序下载网
  • 【面试系列】之二:关于js原型
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • gcc介绍及安装
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • ReactNative开发常用的三方模块
  • 爱情 北京女病人
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 多线程事务回滚
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 你真的知道 == 和 equals 的区别吗?
  • 试着探索高并发下的系统架构面貌
  • 用Canvas画一棵二叉树
  • PostgreSQL之连接数修改
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • #### go map 底层结构 ####
  • #pragam once 和 #ifndef 预编译头
  • #pragma once与条件编译
  • (6)添加vue-cookie
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (HAL库版)freeRTOS移植STMF103
  • (Java数据结构)ArrayList
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • ***测试-HTTP方法
  • .mysql secret在哪_MySQL如何使用索引
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • .net开发时的诡异问题,button的onclick事件无效
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • /var/lib/dpkg/lock 锁定问题
  • @Autowired 与@Resource的区别
  • @Import注解详解
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • []C/C++读取串口接收到的数据程序
  • [2016.7.Test1] T1 三进制异或
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大