CodeChef Chef and Churu Problem

来源:互联网 发布:安卓平板 知乎 编辑:程序博客网 时间:2024/05/29 18:36

Chef and Churu Problem Code: FNCS
Add problem to Todo list
Tweet
链接

All submissions for this problem are available.
Read problems statements in Mandarin Chinese and Russian.
Chef has recently learnt Function and Addition. He is too exited to teach this to his friend Churu. Chef and Churu are very fast friends, they share their knowledge whenever they meet. Chef use to give a lot of exercises after he teaches some concept to Churu.

Chef has an array of N numbers. He also has N functions. Each function will return the sum of all numbers in the array from Li to Ri. So Chef asks churu a lot of queries which are of two types.
Type 1: Change the xth element of the array to y.
Type 2: Return the sum of all functions from m to n.

Now Churu has started to solve, but Chef realize that it is tough for him to decide whether Churu is correct or not. So he needs your help , will you help him out ?
Input Format
First Line is the size of the array i.e. N
Next Line contains N space separated numbers Ai denoting the array
Next N line follows denoting Li and Ri for each functions.
Next Line contains an integer Q , number of queries to follow.
Next Q line follows , each line containing a query of Type 1 or Type 2.
1 x y : denotes a type 1 query,where x and y are integers
2 m n : denotes a type 2 query where m and n are integers
Output Format
For each query of type 2 , output as asked above.
Constraints
1 ≤ N ≤ 105
1 ≤ Ai ≤ 109
1 ≤ Li ≤ N
Li ≤ Ri ≤ N
1 ≤ Q ≤ 105
1 ≤ x ≤ N
1 ≤ y ≤ 109
1 ≤ m ≤ N
m ≤ n ≤ N
Subtask
Subtask 1: N ≤ 1000 , Q ≤ 1000 , 10 points
Subtask 2: R-L ≤ 10 , all x will be distinct ,10 points
Subtask 3: Refer to constraints above , 80 points
Sample Input
5
1 2 3 4 5
1 3
2 5
4 5
3 5
1 2
4
2 1 4
1 3 7
2 1 4
2 3 5
Sample Output
41
53
28
Explanation
Functions values initially :
F[1] = 1+ 2 + 3 = 6
F[2] = 2 + 3 + 4 + 5 = 14
F[3] = 4+5 = 9
F[4] = 3+4+5 = 12
F[5] = 1+2 = 3
Query 1: F[1] + F[2] + F[3] + F[4] = 41
After Update , the Functions are :
F[1] = 10 , F[2] = 18 , F[3] = 9 , F[4] = 16 , F[5] = 3
Query 3: F[1] + F[2] + F[3] + F[4] = 53
Query 4: F[3]+F[4]+F[5] = 28

考完试,交了代码,闲的没事,想整点事,随便搜了个题解,用mjt的名字交了上去,80分,,,,叫我讲题。。。
没关系,有我在hold住全场,lrh说他见过原题,于是我就淡定的走上讲台:“对于考试,我们要合理的利用上厕所的时间,lrh在厕所告诉我他见过原题,然后。。。然后就请他讲吧。”哈哈,果断帅锅lrh。。

哈哈哈。。。

分析:分块+树状数组,,,每次查询的时候,中间完整的块,直接加进答案去,两端的用树状数组解决,还需要对N个函数进行分块,分块处理出每个块内,序列中第i个数被这个块内的函数覆盖的次数, 然后处理出每个块内函数的和,由于是单点更新,所以在维护每个块函数的和的时候是比较好维护的(因为已经知道了第i个数被这个块内的函数覆盖的次数),然后就是区间查询了,直接分块处理就好了。

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#define MAXN 100010#define BLOCK 400#define lowbit(x) (x & (-x))using namespace std;typedef long long LL;int n,m,li[MAXN],ri[MAXN],a[MAXN];LL Bit[MAXN],sumb[BLOCK];int vis[BLOCK][MAXN],unic,Num;inline void read(int &x) {    x = 0; register char c = getchar(); int f = 1;    while(c > '9' || c < '0') { c = getchar(); f = -1; }    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } x *= f;}void Insert(int pos,int val) { for(; pos<=n; pos += lowbit(pos)) Bit[pos] += val; }void UpDate(int x,int y) {    Insert(x,y-a[x]);    for(int i=1; i<=Num; ++i) sumb[i] += (LL) vis[i][x] * (y - a[x]);    a[x] = y;}LL Get_Sum(int pos) {    LL sum = 0;    for(; pos; pos -= lowbit(pos)) sum += Bit[pos];    return sum;}LL Query(int l,int r) {    int lb = (l - 1) / unic + 1,rb = (r - 1) / unic + 1;LL Sum = 0;    if(lb == rb)         for(int i=l; i<=r; ++i) Sum += Get_Sum(ri[i]) - Get_Sum(li[i] - 1);    else  {        for(int i=lb+1; i<=rb-1; ++i) Sum += sumb[i];        for(int i=l; i<=lb*unic; ++i) Sum += Get_Sum(ri[i]) - Get_Sum(li[i] - 1);        for(int i=(rb - 1)*unic+1; i<=r; ++i) Sum += Get_Sum(ri[i]) - Get_Sum(li[i] - 1);    }    return Sum;}int main(int argc,char *argv[]) {    read(n);    for(int i=1; i<=n; ++i) read(a[i]);    for(int i=1; i<=n; ++i) read(li[i]),read(ri[i]);    for(int i=1; i<=n; ++i) Insert(i,a[i]);    int Now = 0;    Num = unic = sqrt(n);    if(unic * unic != n) Num ++;    for(int i=1; i<=n; ++i) {        if(i % unic == 1) ++Now;        vis[Now][li[i]]++,vis[Now][ri[i] + 1]--;    }    for(int i=1; i<=Num; ++i)        for(int j=1; j<=n; ++j) {            vis[i][j] += vis[i][j-1];            sumb[i] += (LL)vis[i][j] * a[j];        }    int opt,x,y; read(m);    while(m--) {        read(opt),read(x),read(y);        if(opt == 1) UpDate(x,y);        else printf("%lld\n",Query(x,y));    }    return 0;}
原创粉丝点击