2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)

题目链接:https://codeforces.com/gym/101991/problem/G

题意:给出 n 个数,q 次询问区间[ li,ri ]之间有多少个 GCD = di 的连续子区间。

题解:类似HDU 5726,可以先看一下这个blog:https://blog.csdn.net/u013569304/article/details/51987053

考虑离线,先预处理出[ 1,n ]之间所有的GCD,同时需要记录每种 GCD 的区间,方法是固定一个右端点R,对于区间[ L,R ],假设 GCD(L,R)= D,可以找到使得GCD(L,R)突变的点 pos,即 x ∈ [ L,pos ] 都有 GCD(x,R) = D,然后利用线段树可以统计出 GCD = D 的区间个数。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define ull unsigned long long
  5 #define mst(a,b) memset((a),(b),sizeof(a))
  6 #define mp(a,b) make_pair(a,b)
  7 #define pi acos(-1)
  8 #define pii pair<int,int>
  9 #define pb push_back
 10 const int INF = 0x3f3f3f3f;
 11 const double eps = 1e-6;
 12 const int maxn = 1e5 + 10;
 13 const int maxm = 1e6 + 10;
 14 const ll mod =  1e9 + 7;
 15
 16 int a[maxn];
 17
 18 struct node {
 19     int l,r,id;
 20 };
 21
 22 bool cmp(node x,node y) {
 23     if(x.id != y.id) return x.id < y.id;
 24     return x.l > y.l;
 25 }
 26
 27 vector<node>vec[maxm];
 28 vector<pii>now,nex;
 29
 30 ll sum[maxn<<2],ans[maxn];
 31 int lazy[maxn<<2];
 32
 33 inline void init(int rt,int l,int r) {
 34     if(!sum[rt] && !lazy[rt]) return ;
 35     sum[rt] = lazy[rt] = 0;
 36     if(l == r) return ;
 37     int mid = (l + r) >> 1;
 38     init(rt<<1,l,mid);
 39     init(rt<<1|1,mid + 1,r);
 40 }
 41
 42 inline void pushdown(int rt,int l,int r) {
 43     if(lazy[rt]) {
 44         int mid = (l + r) >> 1;
 45         lazy[rt<<1] += lazy[rt];
 46         lazy[rt<<1|1] += lazy[rt];
 47         sum[rt<<1] += 1ll * (mid - l + 1) * lazy[rt];
 48         sum[rt<<1|1] += 1ll * (r - mid) * lazy[rt];
 49         lazy[rt] = 0;
 50     }
 51 }
 52
 53 inline void update(int rt,int l,int r,int ql,int qr) {
 54     if(ql <= l && qr >= r) {
 55         lazy[rt]++;
 56         sum[rt] += (ll)(r - l + 1);
 57         return ;
 58     }
 59     pushdown(rt,l,r);
 60     int mid = (l + r) >> 1;
 61     if(qr <= mid) update(rt<<1,l,mid,ql,qr);
 62     else if(ql > mid) update(rt<<1|1,mid + 1,r,ql,qr);
 63     else {
 64         update(rt<<1,l,mid,ql,mid);
 65         update(rt<<1|1,mid + 1,r,mid + 1,qr);
 66     }
 67     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 68 }
 69
 70 inline ll query(int rt,int l,int r,int ql,int qr) {
 71     if(ql <= l && qr >= r) return sum[rt];
 72     pushdown(rt,l,r);
 73     int mid = (l + r) >> 1;
 74     if(qr <= mid) return query(rt<<1,l,mid,ql,qr);
 75     else if(ql > mid) return query(rt<<1|1,mid + 1,r,ql,qr);
 76     else return query(rt<<1,l,mid,ql,mid) + query(rt<<1|1,mid + 1,r,mid + 1,qr);
 77 }
 78
 79 int main() {
 80 #ifdef local
 81     freopen("data.txt", "r", stdin);
 82 //    freopen("data.txt", "w", stdout);
 83 #else
 84     freopen("gcdrng.in", "r", stdin);
 85 #endif
 86     int t;
 87     scanf("%d",&t);
 88     while(t--) {
 89         int n,q;
 90         scanf("%d%d",&n,&q);
 91         for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
 92         for(int i = 1; i <= q; i++) {
 93             int l,r,d;
 94             scanf("%d%d%d",&l,&r,&d);
 95             vec[d].push_back({-i,l,r});
 96         }
 97         nex.clear();
 98         for(int i = 1; i <= n; i++) {
 99             now.clear();
100             now.push_back(mp(a[i],1));
101             for(int j = 0; j < nex.size(); j++) {
102                 pii p = nex[j];
103                 int g = __gcd(now[now.size() - 1].first,p.first);
104                 if(g == now[now.size() - 1].first) now[now.size() - 1].second += p.second;
105                 else now.push_back(mp(g,p.second));
106             }
107             int r = i;
108             for(int j = 0; j < now.size(); j++) {
109                 pii p = now[j];
110                 vec[p.first].push_back({r - p.second + 1,r,i});
111                 r -= p.second;
112             }
113             nex = now;
114         }
115         for(int i = 1; i <= 1e6; i++) {
116             init(1,1,n);
117             sort(vec[i].begin(),vec[i].end(),cmp);
118             for(int j = 0; j < vec[i].size(); j++) {
119                 node p = vec[i][j];
120                 if(p.l > 0) update(1,1,n,p.l,p.r);
121                 else ans[-p.l] = query(1,1,n,p.r,p.id);
122             }
123             vec[i].clear();
124         }
125         for(int i = 1; i <= q; i++) printf("%lld\n",ans[i]);
126     }
127     return 0;
128 }

原文地址:https://www.cnblogs.com/scaulok/p/10089809.html

时间: 2024-10-10 15:06:10

2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)的相关文章

2018 German Collegiate Programming Contest (GCPC 18)

2018 German Collegiate Programming Contest (GCPC 18) Attack on Alpha-Zet 建树,求lca 代码: #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bit

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队博客 C.Coolest Ski Route (记忆化搜索) 题意 给出一个有向图,求出一个权值最长的链, 题解 暴力dfs会超时,所以直接储存每个起点能走到的最远距离 #include<

(寒假GYM开黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

layout: post title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! B.Baby Bites (签到模拟) 按照题意模拟就行了 int a[maxn]; string s; int main() { std::ios::syn

2018 China Collegiate Programming Contest Final (CCPC-Final 2018)(A B G I L)

A:签到题,正常模拟即可. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 5; 4 struct node{ 5 int id, time; 6 }; 7 node a[maxn]; 8 bool cmp(const node &a, const node &b){ 9 if(a.id^b.id) return a.id < b.id; 10 else return a.

模拟赛小结:2018 China Collegiate Programming Contest Final (CCPC-Final 2018)

比赛链接:传送门 跌跌撞撞6题摸银. 封榜后两题,把手上的题做完了还算舒服.就是罚时有点高. 开出了一道奇奇怪怪的题(K),然后ccpcf银应该比区域赛银要难吧,反正很开心qwq. Problem A. Mischievous Problem Setter 00:14 (-2) Solved by Dancepted 良心签到题.WA2吃乳猪. 代码: #include <iostream> #include <cmath> #include <map> #includ

Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)

(本套题算是比较温和吧,就是罚时有点高. B .Baby Bites 题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组. 思路:从左往右依次固定,看是否有矛盾即可. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) using n

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018 Problem A. Can Shahhoud Solve it? Problem B. Defeat the Monsters Problem C. UCL Game Night Problem

2018 ACM-ICPC, Syrian Collegiate Programming Contest

2018 ACM-ICPC, Syrian Collegiate Programming Contest A Hello SCPC 2018! 水题 B Binary Hamming 水题 C Portals 思路:并查集维护连通性 代码: //#pragma GCC optimize(3) //#pragma comment(linker, "/STACK:102400000,102400000") //c++ // #pragma GCC diagnostic error &quo

ACM International Collegiate Programming Contest, JUST Collegiate Programming Contest (2018)

ACM International Collegiate Programming Contest, JUST Collegiate Programming Contest (2018) B. New Assignment 有n个人(1?≤?n?≤?104),有男有女,每个人都有一个id,现在这n个人分成学习互助小组,有三种组队模式,一个男人一组,一个女人一组,一男一女一组,如果要一男一女一组,那么这两人id的gcd要>1.保证任意三个人的gcd=1.求小组的组数最少是多少? 看起来是一个很裸的二