zoukankan      html  css  js  c++  java
  • P4145——线段树点修改&&模板题

    题目

    链接

    题意:对一个数列进行以下两种操作:

    • 给$[l,r]$中的每个数开平方(下取整)
    • 询问$[l,r]$中各个数的和

    解决方法

    显然,区间开平方不满足区间可加性,所以对区间中每个数开平方不能通过标记完成,只能使用暴力的单点修改。因为1e12的数开方6次就变成了1,所以需要修改的次数实际上很少。同时维护一个区间最大值maxv,如果maxv大于1才需要进行开平方操作。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 const int INF = 0x3f3f3f3f;
     6 const int maxn = 100000 + 10;
     7 ll maxv[maxn << 2], sum[maxn << 2];
     8 int n;
     9 ll a[maxn];
    10 
    11 void build(int o, int L, int R)
    12 {
    13     //printf("o:%d  L:%d  R:%d
    ", o, L, R);
    14     int M = L + (R-L) / 2;
    15     if(L == R)
    16     {
    17          maxv[o] = a[L];
    18          sum[o] = a[L];
    19     }
    20     else
    21     {
    22         build(2*o, L, M);
    23         build(2*o+1, M+1, R);
    24         maxv[o] = max(maxv[2*o], maxv[2*o+1]);
    25         sum[o] = sum[2*o] + sum[2*o+1];
    26     }
    27 }
    28 
    29 int ql, qr;    //查询[ql, qr]中的和
    30 void query(int o,int L,int R, ll& ssum)
    31 {
    32     //printf("o:%d  L:%d  R:%d
    ", o, L, R);
    33     if(ql <= L && R <= qr)
    34     {
    35         //maxx =  maxv[o];
    36         ssum = sum[o];
    37     }
    38     else
    39     {
    40         int M = L + (R - L) / 2;
    41         //maxx = -INF;
    42         ll lsum =0, rsum = 0;
    43         if(ql <= M)  query(2*o, L, M, lsum);
    44         if(qr > M)  query(2*o+1, M+1, R, rsum);
    45         //maxx = max(lmax, rmax);
    46         ssum = lsum + rsum;
    47 
    48     }
    49 }
    50 
    51 int cl, cr;  //修改sqrt(A[cl...cr])
    52 void update(int o, int L, int R)
    53 {
    54     //printf("o:%d  L:%d  R:%d
    ", o, L, R);
    55     if(L == R)   //更新叶子结点
    56     {
    57         maxv[o] = (ll)sqrt(maxv[o]);
    58         sum[o] = maxv[o];
    59     }
    60     else
    61     {
    62         int M = L + (R-L)/2;
    63         if(cl <= M && maxv[2*o] > 1)  update(2*o, L ,M);
    64         if(cr > M && maxv[2*o+1] > 1)  update(2*o+1, M+1, R);
    65         maxv[o] = max(maxv[2*o], maxv[2*o+1]);  //更新非叶子结点
    66         sum[o] = sum[2*o] + sum[2*o+1];
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     scanf("%d", &n);
    73     for(int i = 1;i <= n;i++)  scanf("%lld", &a[i]);
    74 
    75     build(1, 1, n);
    76 
    77     int T;
    78     scanf("%d", &T);
    79     while(T--)
    80     {
    81         int order, l, r;
    82         scanf("%d%d%d", &order, &l, &r);
    83         if(l > r)  swap(l, r);
    84         if(order == 0)
    85         {
    86             cl = l; cr = r;
    87             update(1, 1, n);
    88         }
    89         else
    90         {
    91             ll ans = 0;
    92             ql = l; qr = r;
    93             query(1, 1, n, ans);
    94             printf("%lld
    ", ans);
    95         }
    96     }
    97 
    98     return 0;
    99 }

    看讨论区还有分块、树状数组+并查集等做法,Orz.

  • 相关阅读:
    js 数组去重求和 (转载)
    表格插件汇总(转载)
    SQL Server 用一张表的数据更新另一张表的数据(转载)
    C#创建DataTable(转载)
    C# DataTable 和List之间相互转换的方法(转载)
    维度表,实体表,事实表之间的关系
    Scala中foldLeft的总结
    Scala集合Map
    从合并两个Map说开去
    UDAF(用户自定义聚合函数)求众数
  • 原文地址:https://www.cnblogs.com/lfri/p/11152541.html
Copyright © 2011-2022 走看看