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

    Problem Description
    Rikka and Yuta are interested in Phi function (which is known as Euler's totient function).

    Yuta gives Rikka an array A[1..n] of positive integers, then Yuta makes m queries.  

    There are three types of queries: 

    1lr 

    Change A[i] into φ(A[i]), for all i[l,r].

    2lrx 

    Change A[i] into x, for all i[l,r].

    3lr 

    Sum up A[i], for all i[l,r].

    Help Rikka by computing the results of queries of type 3.

     
    Input
    The first line contains a number T(T100) ——The number of the testcases. And there are no more than 2 testcases with n>105

    For each testcase, the first line contains two numbers n,m(n3×105,m3×105)

    The second line contains n numbers A[i]

    Each of the next m lines contains the description of the query. 

    It is guaranteed that 1A[i]107 At any moment.
     
    Output
    For each query of type 3, print one number which represents the answer.
     
    改段求段,用线段树解决,首先预处理好欧拉函数
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    typedef long long LL;
    using namespace std;
    
    const int N = 10000001;
    #define SIZE 300005
    LL p[N]; // phi(N)
    LL a[SIZE],st[SIZE * 4 + 5],n,m;
    LL changed[SIZE * 4 + 5];
    int T;
    LL Left(LL i){
      return 2*i;
    }
    LL Right(LL i){
      return 2*i+1;
    }
    
    void Build_Tree(LL i,LL l,LL r){
      // cout << l << r << endl;
      changed[i] = 0; st[i] = 0;
      if (l == r){
        LL v;
        scanf("%lld",&v);
        st[i] = v;
        changed[i] = v;
      }
      else {
        LL mid = l + (r-l) / 2;
        Build_Tree(Left(i),l,mid);
        Build_Tree(Right(i),mid+1,r);
        st[i] = st[Left(i)] + st[Right(i)];
      }
    }
    
    void Push_Up(LL i){
      st[i] = st[Left(i)] + st[Right(i)];
      if (changed[Left(i)] == changed[Right(i)])
        changed[i] =changed[Left(i)];
      else
        changed[i] = 0;
    }
    
    void Push_Down(LL i,LL l,LL r){
      if (changed[i]){
        LL c = changed[i];
        changed[Left(i)] = c;
        changed[Right(i)] = c;
        LL mid = l + (r-l) / 2;
        st[Left(i)] = (mid-l+1) * c;
        st[Right(i)] = (r-mid) * c;
        changed[i] = 0;
      }
    }
    
    void UpdateE(LL i,LL l,LL r,LL ql,LL qr){
      if (changed[i] && ql <= l && qr >= r){
        changed[i] = p[changed[i]];
        st[i] = (r-l+1) * changed[i];
        return;
      }
      LL mid = l + (r - l) / 2;
      if (l == r) return;
      Push_Down(i,l,r);
      if (ql <= mid) UpdateE(Left(i),l,mid,ql,qr);
      if (qr >= mid + 1) UpdateE(Right(i),mid+1,r,ql,qr);
      Push_Up(i);
    }
    void Update(LL i,LL l,LL r,LL ql,LL qr,LL c){ //ql、qr为需要更新的区间左右端点,addv为需要变更的值
      if (ql <= l && qr >= r) { //与单点更新一样,当当前结点被需要更新的区间覆盖时
        changed[i] = c;
        st[i] = (r-l+1) * c;
        return;
      }
      Push_Down(i,l,r);
      LL mid = l + (r-l) / 2;
      if (ql <= mid) Update(Left(i),l,mid,ql,qr,c);
      if (qr >= mid + 1) Update(Right(i),mid+1,r,ql,qr,c);
      Push_Up(i);
    }
    
    LL Query(LL i,LL l,LL r,LL ql,LL qr){ // 含义同上
      if (ql <= l && qr >= r) return st[i];
      Push_Down(i,l,r);
      LL mid = l + (r-l) / 2,ans = 0;
      if (ql <= mid) ans += Query(Left(i),l,mid,ql,qr);
      if (qr >= mid + 1) ans += Query(Right(i),mid+1,r,ql,qr);
      return ans;
    }
    
    void phi()
    {
        for(int i=1; i<N; i++)  p[i] = i;
        for(int i=2; i<N; i+=2) p[i] >>= 1;
        for(int i=3; i<N; i+=2)
        {
            if(p[i] == i)
            {
                for(int j=i; j<N; j+=i)
                    p[j] = p[j] - p[j] / i;
            }
        }
    }
    
    
    int main(){
      // freopen("test.in","r",stdin);
      // ios::sync_with_stdio(false);
      phi();
      scanf("%d",&T);
      for (int times = 1; times <= T; times ++){
        scanf("%lld %lld",&n,&m);
        Build_Tree(1,1,n);
        for (int i=1;i<=m;i++){
          int l,r,order;
          scanf("%d %d %d",&order,&l,&r);
          LL X;
          switch (order) {
            case 1:
              UpdateE(1,1,n,l,r);
              // for (int j=1;j<=25;j++){
              //   cout << st[j] << " ";
              // }
              // cout << endl;
              break;
            case 2:
              scanf("%lld",&X);
              Update(1,1,n,l,r,X);
              break;
            case 3:
              printf("%lld
    ",Query(1,1,n,l,r));
              break;
          }
        }
      }
      return 0;
    }
    View Code
  • 相关阅读:
    正则表达式学习
    《代码整洁之道》阅读笔记
    PHP手册阅读笔记(一)——XXX
    2014年终总结和2015年规划
    linux之帮助命令——help,man,whereis简介
    企业中git管理代码的基本流程
    推荐几款画韦恩图的在线工具
    HTTPContent-Type的含义
    s s
    asp.net core ServiceProvider
  • 原文地址:https://www.cnblogs.com/ToTOrz/p/7399911.html
Copyright © 2011-2022 走看看