• 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
    ",ans[i]);
    126     }
    127     return 0;
    128 }
  • 相关阅读:
    查询同一表格中姓名相同但身份证号不同的记录
    Liunx常用命令
    判断当前移动端是Android、还是ios、还是微信
    mybatis 返回值问题
    log4j2+mybaits 打印sql操作语句
    java日期格式问题
    eachart图表100px大小原因,及处理办法
    springboot中的默认数据库连接池HikariDataSource
    SpringBoot中logback.xml使用application.yml中属性
    linux 下的vi vim快捷键,命令总结
  • 原文地址:https://www.cnblogs.com/scaulok/p/10089809.html
Copyright © 2020-2023  润新知