区间GCD

输入格式:

输出格式:

样例输入:

glygshcyjcdzy
3
1 11
2 11
2 10

样例输出:

4
2
0

数据范围:

时间限制:

3S

空间限制:

512MB

这题是一个统计题.如果只是两个字母,那就很好做了,然而,三个字母的话,很难直接统计.如果枚举g,还药确定c,d的相对位置,枚举c和d也同样.更何况有Q次询问.

想到这题又是有多次询问,也没有修改操作,而且能在知道[L,R](或[L+1,R+1])的情况下知道[L+1,R]和[L,R+1],所以,我们确定,这题非常适合分块+莫队.更何况,时间复杂度也就在这个级别.

不会莫队的童鞋请自行baidu一下(这一题有多种解法,如线段树).

对于这一题,我们做莫队的核心就是add和remove函数.

我们设g,c,d,gc,cd,gcd分别为这些串(g,c,d,gc,cd,gcd)在当前区间出现的次数.

如果来了一个字母或走了一个字母g,c,d,gc,cd,gcd要相应的更新,具体是什么关系,思考一下就出来了,不在赘述(本蒟蒻不想丢人现眼qwq).

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #define LL long long
 7 using namespace std;
 8 const int maxn=80005;
 9 struct queries{int L,R,index; LL ans;}a[maxn];
10 char s[maxn];
11 int n,blocks,Q;
12 LL g,c,d,gc,cd,gcd,TT;
13 int read(){
14     int x=0; char ch=getchar();
15     while (ch<‘0‘||ch>‘9‘) ch=getchar();
16     while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
17     return x;
18 }
19 bool cmp(queries u,queries v){return u.L/blocks==v.L/blocks?u.R<v.R:u.L<v.L;}
20 bool cmp_id(queries u,queries v){return u.index<v.index;}
21 void removeL(int p,int q){
22     if (s[p]==‘g‘) g--,gc-=c,gcd-=cd; else
23     if (s[p]==‘c‘) c--,cd-=d; else
24     if (s[p]==‘d‘) d--;
25 }
26 void removeR(int p,int q){
27     if (s[q]==‘d‘) d--,cd-=c,gcd-=gc; else
28     if (s[q]==‘c‘) c--,gc-=g; else
29     if (s[q]==‘g‘) g--;
30 }
31 void addL(int p,int q){
32     if (s[p]==‘g‘) g++,gc+=c,gcd+=cd; else
33     if (s[p]==‘c‘) c++,cd+=d; else
34     if (s[p]==‘d‘) d++;
35 }
36 void addR(int p,int q){
37     if (s[q]==‘d‘) d++,cd+=c,gcd+=gc; else
38     if (s[q]==‘c‘) c++,gc+=g; else
39     if (s[q]==‘g‘) g++;
40 }
41 int main(){
42     scanf("%s",s),n=strlen(s),blocks=sqrt(n),TT=(LL)2147483648LL;
43     for (int i=n; i>=1; i--) s[i]=s[i-1]; s[0]=0;
44     cin>>Q;    for (int i=1; i<=Q; i++) a[i].L=read(),a[i].R=read(),a[i].index=i;
45     sort(a+1,a+1+Q,cmp);
46     int curL=1,curR=0; g=c=d=gc=cd=gcd=0;
47     for (int i=1; i<=Q; i++){
48         while (curL<a[i].L) removeL(curL++,curR);
49         while (curR>a[i].R) removeR(curL,curR--);
50         while (curL>a[i].L) addL(--curL,curR);
51         while (curR<a[i].R) addR(curL,++curR);
52         a[i].ans=gcd%TT;
53     }
54     sort(a+1,a+1+Q,cmp_id);
55     for (int i=1; i<=Q; i++) printf("%lld\n",a[i].ans);
56     return 0;
57 }

时间: 2024-07-29 20:52:52

区间GCD的相关文章

dutacm.club 1094: 等差区间(RMQ区间最大、最小值,区间GCD)

1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total Submissions:655   Accepted:54 [Submit][Status][Discuss] Description 已知一个长度为 n 的数组 a[1],a[2],-,a[n],我们进行 q 次询问,每次询问区间 a[l],a[l+1],-,a[r?1],a[r] ,数字从小到大

HDU 5726 GCD 区间GCD=k的个数

GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2742    Accepted Submission(s): 980 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There ar

区间 GCD

区间 GCD题目描述最近 JC 同学刚学会 gcd,于是迷上了与 gcd 有关的问题.今天他又出了一道这样的题目,想要考考你,你能顺利完成吗?给定一个长度为 n 的字符串 s[1..n],串仅包含小写字母.对于区间 [l, r],你需要回答 s[l..r]中有多少个长度为 3 的子序列组成了"gcd",即有多少组 (i, j, k) 满足 l ≤ i < j < k ≤ r, s[i] ='g', s[j] = 'c', s[k] = 'd'.输入格式第一行为一个字符串 s

bzoj 5028: 小Z的加油店——带修改的区间gcd

Description 小Z经营一家加油店.小Z加油的方式非常奇怪.他有一排瓶子,每个瓶子有一个容量vi.每次别人来加油,他会让 别人选连续一段的瓶子.他可以用这些瓶子装汽油,但他只有三种操作: 1.把一个瓶子完全加满: 2.把一个瓶子完全倒空: 3.把一个瓶子里的汽油倒进另一个瓶子,直到倒出瓶子空了或者倒进的瓶子满了. 当然,为了回馈用户,小Z会时不时选择连续一段瓶子,给每个瓶子容积都增加x. 为了尽可能给更多的人加油,每次客户来加油他都想知道他能够倒腾出的汽油量最少是多少? 当然他不会一点汽

Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD

题意: 两个操作, 单点修改 询问一段区间是否能在至多一次修改后,使得区间$GCD$等于$X$ 题解: 正确思路; 线段树维护区间$GCD$,查询$GCD$的时候记录一共访问了多少个$GCD$不被X整除的区间即可,大于一个就NO 要注意的是,如果真的数完一整个区间,肯定会超时,因此用一个外部变量存储数量,一旦超过一个,就停止整个查询 #include <bits/stdc++.h> #define endl '\n' #define ll long long #define IO ios::s

FZU2224 An exciting GCD problem 区间gcd预处理+树状数组

分析:(别人写的) 对于所有(l, r)区间,固定右区间,所有(li, r)一共最多只会有log个不同的gcd值, 可以nlogn预处理出所有不同的gcd区间,这样区间是nlogn个,然后对于询问离线处理, 用类似询问区间不同数字的方法,记录每个不同gcd最后出现的位置,然后用树状数组进行维护 注:我是看了这段代码会的,但是他的nlogn预处理我不会,我会nlog^2n的 dp[i][j]代表以i为右端点,向左延伸2^j个点(包括i)的gcd,然后因为这样的gcd满足递减,所以可以二分找区间 代

hdu 5869 区间gcd的求法及应用

题意:长度n的序列, m个询问区间[L, R], 问区间内的所有连续子段的不同GCD值有多少种. 题解: 1.因为n个数的gcd等于前n-1个数的gcd值再于第n个数gcd一下的值,再加上如果固定终点,区间向前延伸越多gcd必定是非严格递减的,所以我们可以预处理出以每一个数为终点的所有的后缀的gcd,每次求出第i个数为终点后记录下所有的gcd值再与第i+1个数求gcd,这个很好做. 2.将所有的查询按右区间从小到大排序,同时将第一步记录的值在树状数组中更新,然后用树状数组区间求和就好了,这一步在

Luogu T9376 区间GCD

题目背景 无 题目描述 给定一长度为n的动态序列,请编写一种数据结构,要求支持m次操作,包括查询序列中一闭区间中所有数的GCD,与对一闭区间中所有数加上或减去一个值. 输入输出格式 输入格式: 第1行两个数n,m,表示序列长度和操作次数. 第2行n个数ai,表示给定序列. 第3行至第m+2行,每行3~4个数: (1) 1 x y k 表示将[x,y]上的所有数加上k. (2) 2 x y 表示询问[x,y]上所有数的GCD. 输出格式: 对所有操作2,输出一个数,表示询问结果. 输入输出样例 输

E. Kamil and Making a Stream 区间gcd

E. Kamil and Making a Stream 这个题目要用到一个结论,就是区间一个区间长度为n的不同的gcd不会超过logn 个, 其实就是知道这个题目可以暴力就好了. 然后就是对于每一个节点,我都存从祖先到这个节点的所有的gcd,用一个vector存下来. 然后因为这个vector的size 不会很大,所以就可以直接暴力往下转移. #include <cstdio> #include <cstring> #include <cstdlib> #includ