[线段树+区间求和]LightOJ 1183 - Computing Fast Average

 
 
1183 - Computing Fast Average
Time Limit: 2 second(s)Memory Limit: 64 MB

Given an array of integers (0 indexed), you have to perform two types of queries in the array.

1.      1 i j v - change the value of the elements from ith index to jth index to v.

2.      2 i j - find the average value of the integers from ith index to jth index.

You can assume that initially all the values in the array are 0.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case contains two integers: n (1 ≤ n ≤ 105), q (1 ≤ q ≤ 50000), where n denotes the size of the array. Each of the next q lines will contain a query of the form:

1 i j v (0 ≤ i ≤ j < n, 0 ≤ v ≤ 10000)

2 i j (0 ≤ i ≤ j < n)

Output

For each case, print the case number first. Then for each query of the form '2 i j' print the average value of the integers from i to j. If the result is an integer, print it. Otherwise print the result in 'x/y' form, where x denotes the numerator and y denotes the denominator of the result and x and y are relatively prime.

Sample Input

Output for Sample Input

1

10 6

1 0 6 6

2 0 1

1 1 1 2

2 0 5

1 0 3 7

2 0 1

Case 1:

6

16/3

7

Note

Dataset is huge. Use faster i/o methods.

 

题意:给定一个序列,要求可以成段更新和求区间的平均数。

分析:稍微做了点变化,要求输出最简分式,用gcd约下分就可以了。

线段树:点树-成段更新-区间询问。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 111111;
int sum[MAXN<<2],cov[MAXN<<2],t,n,q;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
void build(){
    memset(sum,0,sizeof(sum));
    memset(cov,-1,sizeof(cov));
}
void pushDOWN(int rt,int l,int r){
    if(cov[rt]!=-1){
        int m = (l+r)>>1;
        sum[rt<<1] = (m-l+1)*cov[rt];
        sum[rt<<1|1] = (r-m)*cov[rt];
        cov[rt<<1] = cov[rt<<1|1] = cov[rt];
        cov[rt] = -1;
    }
}
void pushUP(int rt){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l&&R>=r){
        cov[rt] = c;
        sum[rt] = (r-l+1)*c;
        return;
    }
    pushDOWN(rt,l,r);
    int m = (l+r)>>1;
    if(m>=L)update(L,R,c,lson);
    if(m<R)update(L,R,c,rson);
    pushUP(rt);
}
int query(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r){
        return sum[rt];
    }
    pushDOWN(rt,l,r);
    int m = (l+r)>>1,ret = 0;
    if(m>=L)ret+=query(L,R,lson);
    if(m<R)ret+=query(L,R,rson);
    pushUP(rt);
    return ret;
}
int gcd(int a,int b){
    return ((a%b)==0)?b:gcd(b,a%b);
}
void print(int cas,int mo,int so){
    int div = gcd(mo,so);
    mo/=div;so/=div;
    if(so==1){
        printf("%d\n",mo);
    }else if(mo!=0){
        printf("%d/%d\n",mo,so);
    }else{
        printf("%d\n",0);
    }
}
int main(){
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        scanf("%d%d",&n,&q);
        build();
        printf("Case %d:\n",cas);
        while(q--){
            int a,b,c,d;
            scanf("%d",&a);
            if(a==1){
                scanf("%d%d%d",&b,&c,&d);
                update(b,c,d,0,n-1,1);
            }else{
                scanf("%d%d",&b,&c);
                int mo = query(b,c,0,n-1,1);
                print(cas,mo,(c-b+1));
            }
        }
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值