2018徐州网络赛- H-Ryuji doesn't want to study(树状数组/线段树)

Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i].

Unfortunately, the longer he learns, the fewer he gets.

That means, if he reads books from ll to rr, he will get a[l] \times L + a[l+1] \times (L-1) + \cdots + a[r-1] \times 2 + a[r]a[l]×L+a[l+1]×(L−1)+⋯+a[r−1]×2+a[r] (LL is the length of [ ll, rr ] that equals to r - l + 1r−l+1).

Now Ryuji has qq questions, you should answer him:

11. If the question type is 11, you should answer how much knowledge he will get after he reads books [ ll, rr ].

22. If the question type is 22, Ryuji will change the ith book's knowledge to a new value.

Input

First line contains two integers nn and qq (nn, q \le 100000q≤100000).

The next line contains n integers represent a[i]( a[i] \le 1e9)a[i](a[i]≤1e9) .

Then in next qq line each line contains three integers aa, bb, cc, if a = 1a=1, it means question type is 11, and bb, cc represents [ ll , rr ]. if a = 2a=2 , it means question type is 22 , and bb, cc means Ryuji changes the bth book' knowledge to cc

Output

For each question, output one line with one integer represent the answer.

样例输入复制

5 3
1 2 3 4 5
1 1 3
2 5 0
1 4 5

样例输出复制

10
8

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

 

树状数组:  

 

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=j;i<k;i++)
#define per(i,j,k) for(int i=j;i<=k;i++)
#define IO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef  long long ll;
const int maxn = (int)1e5+5;
ll c[maxn];
ll c2[maxn];
ll n;
ll sum(int x,ll *c)
{
    ll ret = 0;
    while(x)
    {
        ret+=c[x];
        x-= (x&-x);
    }
    return ret;
}

void update1(int x,ll val)
{
       while(x<=n)
       {
           c[x]+=val;
           x += (x&-x);
       }
}
void update2(int x,ll val)
{
    while(x<=n)
    {
        c2[x]+=val;
        x += (x&-x);
    }
}


int main(void) {
      int q;
      scanf("%lld %d",&n,&q);
      //cin>>n>>q;

      ll t;
      per(i,1,n)
      {
          cin>>t;
          update1(i,t);
          update2(i,t*(n+1-i));
      }
      while(q--)
      {
          int cho;
          ll s,e;
          scanf("%d%lld%lld",&cho,&s,&e);
          if(cho==1)
          {
              ll ans = sum(e,c2)-sum(s-1,c2)-(n-e)*(sum(e,c)-sum(s-1,c));
              printf("%lld\n",ans);
          }
          else  {
              ll res =sum(s,c)-sum(s-1,c);
              update1(s,e-res);
              res = sum(s,c2)-sum(s-1,c2);
              update2(s,(n+1-s)*e-res);
          }

      }

}

 

线段树:

#include <bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<k;i++)
#define per(i,j,k) for(int i=j;i<=k;i++)
#define IO ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
typedef  long long ll;
const int maxn = (int)1e5+5;
using namespace std;
int n;
ll a[maxn];
ll sum1[maxn<<2];
ll sum2[maxn<<2];
void push_up(int inx,ll *sum)
{
     sum[inx] = sum[inx<<1]+sum[inx<<1|1];
}

void build1(int inx,int l,int r)
{
     if(l==r)
     {
          sum1[inx]=a[l];
         // cout<<sum1[inx]<<endl;
          return;
     }
     int mid = (l+r)>>1;
     build1(inx<<1,l,mid);
     build1(inx<<1|1,mid+1,r);
     push_up(inx,sum1);
}

void build2(int inx,int l,int r)
{
     if(l==r)
     {
          sum2[inx]=a[r]*(n+1-r);
          //cout<<sum2[inx]<<endl;
          return;
     }
     int mid = (l+r)>>1;
     build2(inx<<1,l,mid);
     build2(inx<<1|1,mid+1,r);
     push_up(inx,sum2);
}
void update(int rt,int a, ll b,int l,int r,ll *sum)
{
     if(r==l)
     {
          sum[rt]=b;
          return ;
     }
     int mid = (l+r)>>1;
     if(a<=mid) update(rt<<1,a,b,l,mid,sum);
     else update(rt<<1|1,a,b,mid+1,r,sum);
     push_up(rt,sum);
}
ll query(int rt,int a,ll b, int l,int r,ll *sum)
{
     if(a<=l&&r<=b)  return sum[rt];
     ll ret=0;
     int mid = (l+r)>>1;
     if(a<=mid) ret+=query(rt<<1,a,b,l,mid,sum);
     if(b>mid) ret+=query(rt<<1|1,a,b,mid+1,r,sum);
     return ret;
}
int main(void)
{
     int q;
     cin>>n>>q;
     per(i,1,n) cin>>a[i];
     build1(1,1,n);
     build2(1,1,n);
     while(q--)
     {
          int cho,s;
          ll e;
          cin>>cho>>s>>e;
          if(cho==1)
          {
               ll ans = query(1,s,e,1,n,sum2)-query(1,s,e,1,n,sum1)*(n-e);
               cout<<ans<<endl;
          }
          else
          {
               update(1,s,e,1,n,sum1);
               update(1,s,e*(n+1-s),1,n,sum2);
          }
     }

}    

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值