zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers

    A Simple Problem with Integers

    Time Limit: 5000ms
    Memory Limit: 131072KB
    This problem will be judged on PKU. Original ID: 3468
    64-bit integer IO format: %lld      Java class name: Main
     

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

     

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.Each of the next Q lines represents an operation."C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000."Q a b" means querying the sum of AaAa+1, ... , Ab.

     

    Output

    You need to answer all Q commands in order. One answer in a line.

     

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    Source

     
    解题:学习下树状数组的改段求段。。。确实很奇妙
     

    给你一个数列,每次询问一个区间的和,或者每次将一个区间的所有元素都加上一个数

        树状数组天生用来动态维护数组前缀和,其特点是每次更新一个元素的值,查询只能查数组的前缀和,

    但这个题目求的是某一区间的数组和,而且要支持批量更新某一区间内元素的值,怎么办呢?实际上,

    还是可以把问题转化为求数组的前缀和。

        首先,看更新操作$update(s, t, d)$把区间$A[s]...A[t]$都增加$d$,我们引入一个数组$delta[i]$,表示

    $A[i]...A[n]$的共同增量,n是数组的大小。那么update操作可以转化为:

    1)令$delta[s] = delta[s] + d$,表示将$A[s]...A[n]$同时增加$d$,但这样$A[t+1]...A[n]$就多加了$d$,所以

    2)再令$delta[t+1] = delta[t+1] - d$,表示将$A[t+1]...A[n]$同时减$d$

        然后来看查询操作$query(s, t)$,求$A[s]...A[t]$的区间和,转化为求前缀和,设$sum[i] = A[1]+...+A[i]$,则

                                $A[s]+...+A[t] = sum[t] - sum[s-1]$,

    那么前缀和$sum[x]$又如何求呢?它由两部分组成,一是数组的原始和,二是该区间内的累计增量和, 把数组A的原始

    值保存在数组org中,并且$delta[i]$对$sum[x]$的贡献值为$delta[i] imes (x+1-i)$,那么

                                [ sum[x] = org[1]+...+org[x] + delta[1] imes x + delta[2] imes (x-1) + delta[3] imes (x-2)+...+delta[x] imes 1]

                                             [= org[1]+...+org[x] + sum_{i = 1}^{x}(delta[i] imes (x+1-i))]

                                            [ sum[x] = sum_{i = 1}^{x}(org[i]) + (x+1) imessum_{i = 1}^{x}(delta[i]) - sum_{i = 1}^{x}(delta[i] imes i) ]

    可以转化为 $sum_{i=1}^{x}(org[i]-delta[i]*i)+(x+1)*delta[i]$

    这其实就是三个数组org[i], delta[i]和delta[i]*i的前缀和,org[i]的前缀和保持不变,事先就可以求出来,delta[i]和

    delta[i]*i的前缀和是不断变化的,可以用两个树状数组来维护。

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 using namespace std;
     5 typedef long long LL;
     6 const int maxn = 100010;
     7 LL s[maxn],c[2][maxn];
     8 int n,m;
     9 void add(LL *c,int i,LL val) {
    10     while(i <= n) {
    11         c[i] += val;
    12         i += i&-i;
    13     }
    14 }
    15 LL sum(LL *c,int i,LL ret = 0) {
    16     while(i > 0) {
    17         ret += c[i];
    18         i -= i&-i;
    19     }
    20     return ret;
    21 }
    22 int main() {
    23     char cmd[4];
    24     LL x,y,z;
    25     while(~scanf("%d%d",&n,&m)) {
    26         memset(c,0,sizeof c);
    27         for(int i = 1; i <= n; ++i) {
    28             scanf("%lld",s + i);
    29             s[i] += s[i-1];
    30         }
    31         while(m--) {
    32             scanf("%s",cmd);
    33             if(cmd[0] == 'C') {
    34                 scanf("%lld%lld%lld",&x,&y,&z);
    35                 add(c[0],x,z);
    36                 add(c[0],y+1,-z);
    37                 add(c[1],x,x*z);
    38                 add(c[1],y+1,-z*(y+1));
    39             } else {
    40                 scanf("%lld%lld",&x,&y);
    41                 printf("%lld
    ",s[y] - s[x-1] + (y+1)*sum(c[0],y) - sum(c[1],y) - x*sum(c[0],x-1) + sum(c[1],x-1));
    42             }
    43         }
    44     }
    45     return 0;
    46 }
    View Code

     然后是Splay,灰常灰常慢

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 using namespace std;
      5 typedef long long LL;
      6 const int maxn = 100010;
      7 int seq[maxn],n,m;
      8 struct SplayTree{
      9     int v[maxn],lazy[maxn],fa[maxn],ch[maxn][2],sz[maxn];
     10     LL sum[maxn];
     11     int tot,root;
     12     void newnode(int &x,int key,int f){
     13         v[x = ++tot] = key;
     14         fa[x] = f;
     15         lazy[x] = ch[x][0] = ch[x][1] = 0;
     16         sz[x] = 1;
     17     }
     18     void pushup(int x){
     19         sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + v[x];
     20         sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
     21     }
     22     void pushdown(int x){
     23         if(lazy[x]){
     24             lazy[ch[x][0]] += lazy[x];
     25             lazy[ch[x][1]] += lazy[x];
     26             sum[ch[x][0]] += (LL)lazy[x]*sz[ch[x][0]];
     27             sum[ch[x][1]] += (LL)lazy[x]*sz[ch[x][1]];
     28             v[ch[x][0]] += lazy[x];
     29             v[ch[x][1]] += lazy[x];
     30             lazy[x] = 0;
     31         }
     32     }
     33     void build(int &x,int L,int R,int f){
     34         if(L > R) return;
     35         int mid = (L + R)>>1;
     36         newnode(x,seq[mid],f);
     37         build(ch[x][0],L,mid - 1,x);
     38         build(ch[x][1],mid + 1,R,x);
     39         pushup(x);
     40     }
     41     void init(){
     42         tot = 0;
     43         newnode(root,0,0);
     44         newnode(ch[root][1],0,root);
     45         build(ch[ch[root][1]][0],1,n,ch[root][1]);
     46     }
     47     void rotate(int x,int kd){
     48         int y = fa[x];
     49         pushdown(y);
     50         pushdown(x);
     51         ch[y][kd^1] = ch[x][kd];
     52         fa[ch[x][kd]] = y;
     53         fa[x] = fa[y];
     54         ch[x][kd] = y;
     55         fa[y] = x;
     56         if(fa[x]) ch[fa[x]][y == ch[fa[x]][1]] = x;
     57         pushup(y);
     58     }
     59     void splay(int x,int goal){
     60         while(fa[x] != goal){
     61             if(fa[fa[x]] == goal) rotate(x,x == ch[fa[x]][0]);
     62             else{
     63                 int y = fa[x],z = fa[y],s = (y == ch[z][0]);
     64                 if(x == ch[y][s]){
     65                     rotate(x,s^1);
     66                     rotate(x,s);
     67                 }else{
     68                     rotate(y,s);
     69                     rotate(x,s);
     70                 }
     71             }
     72         }
     73         pushup(x);
     74         if(!goal) root = x;
     75     }
     76     void select(int k,int goal){
     77         int x = root;
     78         while(k != sz[ch[x][0]]){
     79             if(k < sz[ch[x][0]]) x = ch[x][0];
     80             else{
     81                 k -= sz[ch[x][0]] + 1;
     82                 x = ch[x][1];
     83             }
     84         }
     85         splay(x,goal);
     86     }
     87 }spt;
     88 int main(){
     89     char op[5];
     90     int x,y,z;
     91     while(~scanf("%d%d",&n,&m)){
     92         for(int i = 1; i <= n; ++i)
     93             scanf("%d",seq + i);
     94         spt.init();
     95         while(m--){
     96             scanf("%s%d%d",op,&x,&y);
     97             spt.select(x - 1,0);
     98             spt.select(y + 1,spt.root);
     99             int RL = spt.ch[spt.ch[spt.root][1]][0];
    100             if(op[0] == 'C'){
    101                 scanf("%d",&z);
    102                 spt.lazy[RL] += z;
    103                 spt.sum[RL] += z*spt.sz[RL];
    104                 spt.v[RL] += z;
    105             }else printf("%lld
    ",spt.sum[RL]);
    106         }
    107     }
    108     return 0;
    109 }
    View Code
  • 相关阅读:
    .NET Interop 工具集
    关于正弦波的算法
    Windows Phone 系列 本地数据存储
    Xaml cannot create an instance of “X”
    Windows Phone 系列 使用 MVVM绑定时无法获取当前值
    Windows Phone 系列 应用程序图标无法显示
    Windows Phone 系列 WPConnect无法上网的问题
    Windows Phone 系列 使用 Windows Phone 保存铃声任务
    WP7.5提交应用
    Windows Phone 系列 动态删除ObservableCollection
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4784119.html
Copyright © 2011-2022 走看看