莫队分块

今天兔哥讲了一波莫队,比较有趣,先加一个链接,这是她的教程

rabbithu.cnblogs.com

这里就不详细说了,其实就是两个指针来优化的暴力。一开始排序函数有问题,没用上莫队的核心思想:把查询区间先排序,第一关键字是左指针所在的区间(注意,不是大小),第二关键字是右指针的大小。

然后一点点模拟就行了,左指针向前就减,否则加。

这里有一道板子题

题目描述HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
输入输出格式
输入格式:第一行:一个整数N,表示项链的长度。第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。第三行:一个整数M,表示HH 询问的个数。接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。输出格式:M 行,每行一个整数,依次表示询问对应的答案。

直接贴代码(数据加强之后AC不了,但貌似所有的算法都AC不了?)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll que[500010],n,m,bk;
struct node{int ans;int l,r;
};
node k[200010];
int pl = 1,pr = 0;
bool cmp(node a,node b)
{if(a.l / bk != b.l / bk){return a.l < b.l;}else{return a.r < b.r;}
}
ll cnt[200010],num = 0;
void add(int a)
{if(!cnt[a])num++;cnt[a]++;
}
void del(int a)
{cnt[a]--;if(!cnt[a])num--;
}
ll ans[200010];
int main()
{cin>>n;bk = ceil(sqrt(n));for(int i = 1;i <= n;i++){scanf("%lld",&que[i]);}cin>>m;for(int i = 1;i <= m;i++){scanf("%d%d",&k[i].l,&k[i].r);k[i].ans = i;}sort(k + 1,k + m + 1,cmp);for(int i = 1;i <= m;i++){while(pl < k[i].l)del(que[pl++]);while(pl > k[i].l)add(que[--pl]);while(pr > k[i].r)del(que[pr--]);while(pr < k[i].r)add(que[++pr]);ans[k[i].ans] = num;}for(int i = 1;i <= m;i++){printf("%lld\n",ans[i]);}return 0;
}

还有一个题,是莫队的来源,好像莫队是队长从这一题的论文答辩发明的。

题目描述作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。然而数据中有L=R的情况,请特判这种情况,输出0/1。
输入输出格式
输入格式:输入文件第一行包含两个正整数N和M。N为袜子的数量,M为小Z所提的询问的数量。接下来一行包含N个正整数Ci,其中Ci表示第i只袜子的颜色,相同的颜色用相同的数字表示。再接下来M行,每行两个正整数L,R表示一个询问。输出格式:包含M行,对于每个询问在一行中输出分数A/B表示从该询问的区间[L,R]中随机抽出两只袜子颜色相同的概率。若该概率为0则输出0/1,否则输出的A/B必须为最简分数。(详见样例)输入输出样例
输入样例#1: 复制6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6输出样例#1: 复制2/5
0/1
1/1
4/15

 这个是计数,但是本质上没什么区别,上代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll que[50010],bk,n,m;
struct node{int ans;int l,r;
};
node k[50010];
ll pl = 1,pr = 0;
ll ava[50010],bvb[50010];
bool cmp(node a,node b)
{if(a.l / bk == b.l / bk){return a.r < b.r;}else{return a.l < b.l;}
}
ll gcd(ll a,ll b)
{ll p;while(a % b != 0){p = a % b;a = b;b = p;}return b;
}
ll cnt[50010],num = 0;
void add(int a)
{num -= cnt[a] * cnt[a];cnt[a]++;num += cnt[a] * cnt[a];
}
void del(int a)
{num -= cnt[a] * cnt[a];cnt[a]--;num += cnt[a] * cnt[a];
}
ll ans[50010],aa,bb,cc;
int main()
{cin>>n>>m;for(int i = 1;i <= n;i++){scanf("%lld",&que[i]);}bk = ceil(sqrt(n));for(int i = 1;i <= m;i++){scanf("%d%d",&k[i].l,&k[i].r);k[i].ans = i;}sort(k + 1,k + m + 1,cmp);for(int i = 1;i <= m;i++){if(k[i].l == k[i].r){ava[k[i].ans] = 0;bvb[k[i].ans] = 1;continue;}while(pl < k[i].l)del(que[pl++]);while(pl > k[i].l)add(que[--pl]);while(pr > k[i].r)del(que[pr--]);while(pr < k[i].r)add(que[++pr]);pl = k[i].l;aa = num + k[i].l - k[i].r - 1;bb = (ll)(k[i].r - k[i].l + 1) * (k[i].r - k[i].l);cc = gcd(aa,bb);aa /= cc;bb /= cc;ava[k[i].ans] = aa;bvb[k[i].ans] = bb;
//        cout<<aa<<"/"<<cc<<endl;
    }for(int i = 1;i <= m;i++){printf("%lld/%lld\n",ava[i],bvb[i]);}return 0;
}

但是莫队的修改好像复杂度不是很优秀,而且不能在线只能离线处理,所以我又学了一个其他的结构:分块

再附上一个链接,讲的超级好:

http://hzwer.com/8053.html

其实这种东西和线段树区别不大,但是线段树好像复杂度更好?

然后去钢了一道黑题,做的怀疑人生,最后抄代码过的

题目背景亲爱的哥哥:你在那个城市里面过得好吗?我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!哥哥你要快点回来哦!爱你的妹妹 VioletAzure 读完这封信之后微笑了一下。“蒲公英吗……”
题目描述在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 (a1,a2..an)(a_1,a_2..a_n)(a1​,a2​..an​) ,其中 aia_iai​ 为一个正整数,表示第i棵蒲公英的种类编号。而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。注意,你的算法必须是在线的
输入输出格式
输入格式:第一行两个整数 n,m ,表示有n株蒲公英,m 次询问。接下来一行n个空格分隔的整数 aia_iai​ ,表示蒲公英的种类再接下来m 行每行两个整数 l0,r0l_0,r_0l0​,r0​ ,我们令上次询问的结果为 x(如果这是第一次询问, 则 x=0)。令 l=(l0+x−1)modn+1,r=(r0+x−1)modn+1l=(l_0+x-1)\bmod n + 1,r=(r_0+x-1) \bmod n + 1l=(l0​+x−1)modn+1,r=(r0​+x−1)modn+1 ,如果 l>r,则交换 l,r 。最终的询问区间为[l,r]。输出格式:输出m 行。每行一个整数,表示每次询问的结果。

这个题的思路不算难,就是离散化+分块处理在线找众数,但是代码真是狗

#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m,blo,id;
int v[500005],bl[500005];
int f[1005][1005];  //f[i][j]表示i~j的众数是多少 
map<int,int>mp;
int val[500005],cnt[500005];
vector<int>ve[500005];
void pre(int x)
{   memset(cnt,0,sizeof(cnt));int mx = 0,ans = 0;for(int i=(x - 1) * blo + 1;i <= n;i++){       cnt[v[i]]++;int t = bl[i];if(cnt[v[i]] > mx || (cnt[v[i]] == mx && val[v[i]] < val[ans])) //找x~t真正的众数 ans = v[i],mx = cnt[v[i]];f[x][t] = ans;}
}
int query(int l,int r,int x)
{int t = upper_bound(ve[x].begin(),ve[x].end(),r) - lower_bound(ve[x].begin(),ve[x].end(),l);return t;
} 
int query(int a,int b)
{int ans,mx;ans = f[bl[a] + 1][bl[b] - 1];mx = query(a,b,ans);  //整区间里的众数 for(int i = 1;i <= min(blo * bl[a],b);i++){int t = query(a,b,v[i]);if(t > mx || (t == mx && val[v[i]] < val[ans])){ans = v[i];mx = t;}}if(bl[a] != bl[b]){for(int i = (bl[b] - 1) * blo + 1;i <= b;i++){int t = query(a,b,v[i]);if(t > mx || (t == mx && val[v[i]] < val[ans]))ans = v[i],mx = t;}}return ans;
}
int main()
{scanf("%d%d",&n,&m);blo = 200;int ans = 0;for(int i = 1;i <= n;i++){scanf("%d",&v[i]);if(!mp[v[i]]){mp[v[i]] = ++id; //离散化 val[id] = v[i];    //第一次出现的位置
        }v[i] = mp[v[i]];ve[v[i]].push_back(i);}for(int i = 1;i <= n;i++)     //处理i在第几个块bl[i] = (i - 1) / blo + 1;for(int i = 1;i <= bl[n];i++)  //预处理f数组 
    pre(i);for(int i = 1;i <= m;i++){int a,b;scanf("%d%d",&a,&b);a = (a + ans - 1) % n + 1;b = (b + ans - 1) % n + 1;if(a > b)swap(a,b);ans = val[query(a,b)];printf("%d\n",ans);}return 0;
}

大家加油!!!

转载于:https://www.cnblogs.com/DukeLv/p/9160738.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/570749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Kettle 闪退问题解决方案

我们在搭建kettle平台时&#xff0c;往往会搭建两种平台&#xff0c;一种win、一种是linux。在windows上进行kettle ETL测试工作&#xff0c;测试成功之后&#xff0c;会发布到linux服务器上&#xff0c;这就出现了一下问题——linux执行ktr文件&#xff0c;界面闪退&#xff0…

django-总体

纲领 建立项目时&#xff0c;首先需要以规范的方式对项目进行描述&#xff0c;再建立虚拟环境&#xff0c;以便在其中创建项目。 创建项目后&#xff0c;创建app&#xff0c;并在项目的settings.py中“安装”该app 随后&#xff0c;就是根据项目描述编写urls.py、view层、model…

Python的元组被设计成不可变的影响

实际上元组是跟列表非常相近的另一种容器类型&#xff0c;元组和列表看起来不同的一点是元组用的是圆括号而列表用的是方括号。而功能上&#xff0c;元组和列表相比有一个很重要的区别&#xff0c;元组是一种不可变类型。正是因为这个原因元组能做一些列表不能做的事情……用做…

JS将数字转换为中文

<!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>JS将数字转换为中文</title> </head> <body> <script>// 定义转换函数function transform(tranvalue){try{var i1;var dw2 new Array("&quo…

IE上ORACLE OEM 证书错误 , 导航阻止,无法”继续浏览此网站”

文章转载自&#xff1a;http://blog.51cto.com/cswggod/1193266 仅用于个人学习&#xff0c;知识收藏 本文是我安装ORACLE11g后客户端IE访问不了是出现的&#xff0c;无奈下找OTN上help&#xff0c; 结果很lucky的被解脱了。 网站是&#xff1a;https://forums.oracle.com/for…

testng使用DataProvider+Excel实现DDT

DDT&#xff0c;即数据驱动测试 Data Driver Test&#xff0c;我曾经记录了一篇关于python的DDT框架&#xff08;ExcelDDT数据驱动实例&#xff09;&#xff0c;那么java中的DDT是怎么样的呢&#xff1f;在java中&#xff0c;可以用testng的DataProvider和Excel实现。 首先建一…

Linux安装Oracle12C 过程及遇到的问题

一、环境介绍 1、系统环境&#xff1a;CentOS7.1 Oracle版本&#xff1a;12C 12.1.0 二、安装过程 1、安装过程文档见百度云上的文档 链接&#xff1a;https://pan.baidu.com/s/1nvd07NF 密码&#xff1a;mey9 2、安装完后登录数据库 su oracle source ~/.bash_profiel…

sqlserver服务启动后停止,传递给数据库 'master' 中的日志扫描操作的日志扫描号无效...

电脑异常重启&#xff0c;导致SqlServer服务启动后&#xff0c;自动停止&#xff0c;在【计算机管理】-【事件查看器】-【windows日志】中进行查看系统错误日志&#xff0c;在【应用程序】下发现可能的错误信息有以下两条&#xff1a; 1、错误&#xff1a;传递给数据库 master …

云监控 Ganglia 安装步骤 (含python module)

文章转载自&#xff1a;https://my.oschina.net/duangr/blog/181585 &#xff0c;仅用于个人学习、收藏&#xff0c;转载请注明原作者地址。 前言 最近在研究云监控的相关工具,感觉ganglia颇有亮点,能从一个集群整体的角度来展现数据. 但是安装过程稍过复杂,相关依赖稍多…

container-with-most-water(最大蓄水问题)

题目描述&#xff1a; Given n non-negative integers a1 , a2 , ..., an , where each represents a point at coordinate (i, ai ). n vertical lines are drawn such that the two endpoints of line i is at (i, ai ) and (i, 0). Find two lines, which together with x-a…

使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决

一、参考文档&#xff1a; 1、https://www.rittmanmead.com/blog/2014/03/using-sqoop-for-loading-oracle-data-into-hadoop-on-the-bigdatalite-vm/ 2、http://www.cnblogs.com/bjtu-leefon/archive/2013/06/28/3160549.html 二、使用脚本 ----sqoop import zdsd 使用注…

POJ1426-Find The Multiple(DFS)

给出一个整数n&#xff0c;(1 < n < 200)。求出任意一个它的倍数m&#xff0c;要求m必须只由十进制的0或1组成。 #include <iostream>using namespace std;int N,flag;void DFS(int m,long long n) {if(m19) return;if(flag) return;if(n%N0){flag1;cout<<n&…

Spark集群,多个版本Python/Python Package管理

文章转载自&#xff1a;http://blog.csdn.net/gongbi917/article/details/52369025 仅用于个人学习备忘收藏&#xff0c;转载请注明原文地址 进年来&#xff0c;越来越多的数据科学家、分析人员、数据工程师运用Python语言进行数据分析和机器学习。Spark在0.7版本开始支持Pyth…

【网络流24题】【LOJ6224】深海机器人问题(最大费用最大流)

problem 给定一个n*m的网格&#xff0c;每条边上有一个权值给定每个机器人的出发位置和目标位置求权值最大solution 拆边&#xff0c;每条边拆成2条&#xff0c;第一条容量1&#xff0c;费用c[i]&#xff0c;第二条容量inf,费用0&#xff1b;建超级源汇&#xff08;s到每个出发…

Oracle创建表空间、用户、分配权限、导出、导入数据

文章转载&#xff1a;https://segmentfault.com/a/1190000006704150 仅用于个人学习、收藏自查&#xff0c;谢谢原作者。 以系统管理员登录&#xff0c;命令&#xff1a;sqlplus / as sysdba #首先需要 su - oracle 进入到oracle用户下 一、分为四步 /第1步&#xff1a;创…

函数简介

一、函数 函数就是一个功能&#xff0c;一个方法&#xff0c;简化代码。#一个函数只做一件事#重复的代码就是低级的#实现同样的功能&#xff0c;代码越少越好 函数必须得调用才能执行。 1、函数的简单介绍&#xff0c;如下 1 def say(name):# 函数&#xff0c;形参&#xff0c;…

ORA-65096: 公用用户名或角色名无效引发的思考

解决方式&#xff1a; alter session set "_ORACLE_SCRIPT"true; alter session set containerPDBORCL;原因&#xff1a;查官方文档得知“试图创建一个通用用户&#xff0c;必需要用C##或者c##开头”&#xff0c;这时候心里会有疑问&#xff0c;什么是common user&am…

VS封装给Unity使用的DLL

首先: 注意两点,一个是选择3.5,Unity最高支持到3.5 然后要选择第二个FrameWork类库 第一个会报错 然后导入Unity dll 我Unity安装在F:\AppLicationWorkSpace\Unity5.6.2\Unity\Editor\Data\Managed 用哪个导入哪个 然后生成 Ok 把生成的DLL放到Unity里就可以使用了 继续写…

ftp与sftp及sftp和scp的区别

FTP VS SFTP FTP是文件传输协议。在网站上&#xff0c;如果你想把文件和人共享&#xff0c;最便捷的方式莫过于把文件上传到FTP服务器上&#xff0c;其他人通过FTP客户端程序来下载所需要的文件。 FTP进行文件传输需要通过端口进行。一般所需端口为&#xff1a; 1. 控制链路—T…

Kong API Gateway部署手册----安装

文章转载&#xff1a;http://www.nxops.cn/post/97.html