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 }

猜你喜欢

转载自www.cnblogs.com/scaulok/p/10089809.html