hdu 5419 Victor and Toys 线段树成段更新

来源:互联网 发布:linux ntpclient 编辑:程序博客网 时间:2024/05/26 08:43

Victor and Toys

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)
Total Submission(s): 156    Accepted Submission(s): 54


Problem Description
Victor has n toys, numbered from 1 to n. The beauty of the i-th toy is wi.

Victor has a sense of math and he generates m intervals, the i-th interval is [li,ri]. He randomly picks 3 numbers i,j,k(1i<j<km), and selects all of the toys whose number are no less than max(li,lj,lk) and no larger than min(ri,rj,rk). Now he wants to know the expected sum of beauty of the selected toys, can you help him?
 

Input
The first line of the input contains an integer T, denoting the number of test cases.

In every test case, there are two integers n and m in the first line, denoting the number of the toys and intervals.

The second line contains n integers, the i-th integer wi denotes that the beauty of the i-th toy.

Then there are m lines, the i-th line contains two integers li and ri.

1T10.

1n,m50000.

1wi5.

1lirin.
 

Output
Your program should print T lines : the i-th of these denotes the answer of the i-th case.

If the answer is an integer, just print a single interger, otherwise print an irreducible fraction likep/q.
 

Sample Input
13 41 1 52 31 33 31 1
 

Sample Output
5/4
 

Source
BestCoder Round #52 (div.2)
 

Recommend
hujie   |   We have carefully selected several similar problems for you:  5421 5420 5418 5417 5416 
题意,给出n个点,m个区间,先出三个区间,左值取最大,右值取最小,区间和的期望。

考虑每一个点,对结果的影响,如果,一个点包括了x个区间,那么,就有C(x,3)个w[i]在分子上,分母为C(m,3);所以最终的问题就是要求每个点,所点的区间数,真接用区间的开头加1,结尾减1,复杂度为o(n ),如果用线段树成段更新,复杂度为o(n * log(n);注意不要爆了long long,所以分子分母先都除上6.

第一种方法

#define N 300005#define M 100005#define maxn 205#define SZ 26#define MOD 1000000000000000007#define lson (now<<1)#define rson (now<<1|1)int n,T,m,w[N],a,b,num[N],pri[N][2];int main(){    while(S(T)!=EOF)    {        while(T--){            S2(n,m);            For(i,1,n+1){                scan_d(a);                w[i] = a;                num[i] = 0;                pri[i][0] =  pri[i][1] = 0;            }            FI(m){                scan_d(a);scan_d(b);                pri[a][0]++;                pri[b][1]++;            }            int nn = 0;            for(int i = 1;i<=n;i++){                nn += pri[i][0];                num[i] = nn;                nn -= pri[i][1];            }            ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6;            For(i,1,n+1){                ll t = (ll) num[i];                if(t >= 3){                    ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6;                }            }            if(ans == 0){                printf("%lld\n",ans);                continue;            }            ll gc = gcd(ans,s2);            ans /= gc;s2 /= gc;            if(s2 == 1)                printf("%lld\n",ans);            else                printf("%lld/%lld\n",ans,s2);        }    }    //fclose(stdin);    //fclose(stdout);    return 0;}


第二种方法(线段树)

#define N 300005#define M 100005#define maxn 205#define SZ 26#define MOD 1000000000000000007#define lson (now<<1)#define rson (now<<1|1)int n,T,m,w[N],a,b;struct node{    int sum;};node tree[N*4];void pushDown(int now){    if(tree[now].sum > 0){        tree[lson].sum  += tree[now].sum;        tree[rson].sum += tree[now].sum;        tree[now].sum = 0;    }}void buildTree(int l,int r,int now){    tree[now].sum = 0;    if(l >= r){        return ;    }    int mid = (l+r)>>1;    buildTree(l,mid,lson);    buildTree(mid+1,r,rson);}void updateTree(int l,int r,int now,int s,int e,int c){    if(s <= l && e>= r){        tree[now].sum += c;        return ;    }    pushDown(now);    int mid = (l+r)>>1;    if(s <= mid) updateTree(l,mid,lson,s,e,c);    if(e > mid) updateTree(mid+1,r,rson,s,e,c);}int queryTree(int l,int r,int now,int s,int e){    if(s <= l && e>= r){        return tree[now].sum;    }    pushDown(now);    int mid = (l+r)>>1;    if(s <= mid) return queryTree(l,mid,lson,s,e);    if(e > mid) return queryTree(mid+1,r,rson,s,e);    return 0;}int main(){    while(S(T)!=EOF)    {        while(T--){            S2(n,m);            buildTree(1,n,1);            For(i,1,n+1){                scan_d(a);                w[i] = a;            }            FI(m){                scan_d(a);scan_d(b);                updateTree(1,n,1,a,b,1);            }            ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6;            For(i,1,n+1){                ll t = (ll) queryTree(1,n,1,i,i);                if(t >= 3){                    ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6;                }            }            if(ans == 0){                printf("%lld\n",ans);                continue;            }            ll gc = gcd(ans,s2);            ans /= gc;s2 /= gc;            if(s2 == 1)                printf("%lld\n",ans);            else                printf("%lld/%lld\n",ans,s2);        }    }    //fclose(stdin);    //fclose(stdout);    return 0;}


0 0
原创粉丝点击