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;
}