zoukankan      html  css  js  c++  java
  • HDU 5634 Rikka with Phi

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5634

    --------------------------------------------------------------------------------------------

    官方题解上给的是用平衡树写 不过用类似的思路 也是可以用线段树去写的

    操作$2$区间赋为相同值可以直接按照常规的线段树的题目去写

    操作$1$是只减不增的 而且最多$log$次会减少到$1$

    所以大量使用$1$操作会出现许多连续的$1$

    当访问到区间都是一个值显然可以直接返回结果

    而在这之前我们变可以把区间不为相同值的进行暴力取$phi$

    尽管操作$2$会使区间值增加 但如果把连续的相同值算作$1$个区间的话

    操作$2$每次最多只会增加$1$个区间 所以均摊下来并不会使操作$1$的复杂度增加

    最终复杂度也是$O((n + m)logn)$的

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 using namespace std;
      6 const int N = 1e7, L = 7e5, T = 3e5 + 10;
      7 bool used[N + 10];
      8 int phi[N + 10], p[L];
      9 int a[T], flag[T << 2];
     10 long long sum[T << 2];
     11 int len, t, n, m;
     12 void getprime()
     13 {
     14     phi[1] = 1;
     15     for(int i = 2; i <= N; ++i)
     16     {
     17         if(! used[i])
     18         {
     19             p[++len] = i;
     20             phi[i] = i - 1;
     21         }
     22         for(int j = 1; j <= len && i * p[j] <= N; ++j)
     23         {
     24             used[i * p[j]] = 1;
     25             if(i % p[j] == 0)
     26             {
     27                 phi[i * p[j]] = phi[i] * p[j];
     28                 break;
     29             }
     30             else
     31                 phi[i * p[j]] = phi[i] * (p[j] - 1);
     32         }
     33     }
     34 }
     35 void build(int x, int L, int R)
     36 {
     37     if(L == R)
     38     {
     39         sum[x] = flag[x] = a[L];
     40         return;
     41     }
     42     int mid = (L + R) >> 1;
     43     build(x << 1, L, mid);
     44     build(x << 1 | 1, mid + 1, R);
     45     sum[x] = sum[x << 1] + sum[x << 1 | 1];
     46     flag[x] = (flag[x << 1] == flag[x << 1 | 1] ? flag[x << 1] : 0);
     47 }
     48 void update2(int x, int L, int R, int tl, int tr, int y)
     49 {
     50     if(L <= tl && tr <= R)
     51     {
     52         flag[x] = y;
     53         sum[x] = (long long)flag[x] * (tr - tl + 1);
     54         return;
     55     }
     56     int mid = (tl + tr) >> 1;
     57     if(flag[x])
     58     {
     59         update2(x << 1, tl, mid, tl, mid, flag[x]);
     60         update2(x << 1 | 1, mid + 1, tr, mid + 1, tr, flag[x]);
     61     }
     62     if(L <= mid)
     63         update2(x << 1, L, R, tl, mid, y);
     64     if(mid < R)
     65         update2(x << 1 | 1, L, R, mid + 1, tr, y);
     66     sum[x] = sum[x << 1] + sum[x << 1 | 1];
     67     flag[x] = (flag[x << 1] == flag[x << 1 | 1] ? flag[x << 1] : 0);
     68 }
     69 void update1(int x, int L, int R, int tl, int tr)
     70 {
     71     if(flag[x] && L <= tl && tr <= R)
     72     {
     73         flag[x] = phi[flag[x]];
     74         sum[x] = (long long)flag[x] * (tr - tl + 1);
     75         return;
     76     }
     77     int mid = (tl + tr) >> 1;
     78     if(flag[x])
     79     {
     80         update2(x << 1, tl, mid, tl, mid, flag[x]);
     81         update2(x << 1 | 1, mid + 1, tr, mid + 1, tr, flag[x]);
     82     }
     83     if(L <= mid)
     84         update1(x << 1, L, R, tl, mid);
     85     if(mid < R)
     86         update1(x << 1 | 1, L, R, mid + 1, tr);
     87     sum[x] = sum[x << 1] + sum[x << 1 | 1];
     88     flag[x] = (flag[x << 1] == flag[x << 1 | 1] ? flag[x << 1] : 0);
     89 }
     90 long long query(int x, int L, int R, int tl, int tr)
     91 {
     92     if(L <= tl && tr <= R)
     93         return sum[x];
     94     int mid = (tl + tr) >> 1;
     95     if(flag[x])
     96     {
     97         update2(x << 1, tl, mid, tl, mid, flag[x]);
     98         update2(x << 1 | 1, mid + 1, tr, mid + 1, tr, flag[x]);
     99     }
    100     long long re = 0;
    101     if(L <= mid)
    102         re += query(x << 1, L, R, tl, mid);
    103     if(mid < R)
    104         re += query(x << 1 | 1, L, R, mid + 1, tr);
    105     return re;
    106 }
    107 int main()
    108 {
    109     getprime();
    110     scanf("%d", &t);
    111     while(t--)
    112     {
    113         scanf("%d%d", &n, &m);
    114         for(int i = 1; i <= n; ++i)
    115             scanf("%d", &a[i]);
    116         build(1, 1, n);
    117         int op, x, y, z;
    118         while(m--)
    119         {
    120             scanf("%d%d%d", &op, &x, &y);
    121             if(op == 1)
    122                 update1(1, x, y, 1, n);
    123             else if(op == 2)
    124             {
    125                 scanf("%d", &z);
    126                 update2(1, x, y, 1, n, z);
    127             }
    128             else
    129                 printf("%lld
    ", query(1, x, y, 1, n));
    130         }
    131     }
    132     return 0;
    133 }
  • 相关阅读:
    ContentControl 嵌套后 Foreground 无法继承
    Windows Phone 开发学习
    Windows 8 Metro 风格应用开发
    微信小程序中时间戳和日期的相互转换
    二维数组,要求按考试分数高到低排序,如果考试分数相同就按违纪扣分低到高排序
    微信小程序实现按首字母检索城市列表
    微信40125错误
    sublime text3 英文版转为中文版
    html5代码如何转成小程序代码
    阿里云刘强:无影云电脑构建云上安全办公室
  • 原文地址:https://www.cnblogs.com/sagitta/p/5204066.html
Copyright © 2011-2022 走看看