1. 程式人生 > >Codeforces 276C Little Girl and Maximum Sum(線段樹的區間更新)

Codeforces 276C Little Girl and Maximum Sum(線段樹的區間更新)

The little girl loves the problems on array queries very much.

One day she came across a rather well-known problem: you've got an array of nelements (the elements of the array are indexed starting from 1); also, there are qqueries, each one is defined by a pair of integers liri (1 ≤ li ≤ ri ≤ n). You need to find for each query the sum of elements of the array with indexes from l

i to ri, inclusive.

The little girl found the problem rather boring. She decided to reorder the array elements before replying to the queries in a way that makes the sum of query replies maximum possible. Your task is to find the value of this maximum sum.

Input

The first line contains two space-separated integers n

 (1 ≤ n ≤ 2·105) and q (1 ≤ q ≤ 2·105) — the number of elements in the array and the number of queries, correspondingly.

The next line contains n space-separated integers ai (1 ≤ ai ≤ 2·105) — the array elements.

Each of the following q lines contains two space-separated integers li and ri (1 ≤ li ≤ r

i ≤ n) — the i-th query.

Output

In a single line print a single integer — the maximum sum of query replies after the array elements are reordered.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cincout streams or the %I64d specifier.

Example Input
3 3
5 3 2
1 2
2 3
1 3
Output
25
Input
5 3
5 2 4 1 3
1 5
2 3
2 3
Output
33

題解:

題意:

給你一個長度為n的序列,你可以任意排序,然後在m個詢問區間[l,r]內的和,最後累加這些和,讓你求出能得到的和的最大值

思路:

一開始暴力模擬,華麗得tle了,然後換成了線段樹就ac了,問了老劉他們說是看題解不用線段樹用類似於樹狀陣列的方法模擬也可以做出來。。。我說別人怎麼a得那麼快

我的思路:

就是先按從大到小對陣列排序,然後就是用一顆全為0的線段樹進行區間更新(要用lazy tag)每次區間內所有值+1,最後遍歷所有不為0的子節點放進一個數組裡面從大到小排序,最後兩個陣列相乘累加就是答案

程式碼:

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<string>
#include<stdio.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<deque>
#include<algorithm>
#define ll long long
#define INF 1008611111
#define M (t[k].l+t[k].r)/2
#define lson k*2
#define rson k*2+1
using namespace std;
int a[200005];
int b[200005];
int ans;
int cmp(int x,int y)
{
    return x>y;
}
struct node
{
    int l,r;
    ll sum;
    int tag;
    int length()
    {
        return r-l+1;
    }
}t[200005*4];
void pushup(int k)
{
    t[k].sum=t[lson].sum+t[rson].sum;
}
void pushdown(int k)
{
    if(t[k].tag)
    {
        t[lson].sum+=t[lson].length()*t[k].tag;
        t[rson].sum+=t[rson].length()*t[k].tag;
        t[lson].tag+=t[k].tag;
        t[rson].tag+=t[k].tag;
        t[k].tag=0;
    }
}
void Build(int l,int r,int k)
{
    t[k].l=l;
    t[k].r=r;
    t[k].tag=0;
    if(l==r)
    {
        t[k].sum=0;
        return;
    }
    int mid=M;
    Build(l,mid,lson);
    Build(mid+1,r,rson);
    pushup(k);
}
void update(int l,int r,int k)
{
    if(l==t[k].l&&r==t[k].r)
    {
        t[k].sum+=t[k].length();
        t[k].tag+=1;
        return;
    }
    pushdown(k);
    int mid=M;
    if(r<=mid)
        update(l,r,lson);
    else if(l>mid)
        update(l,r,rson);
    else
    {
        update(l,mid,lson);
        update(mid+1,r,rson);
    }
    pushup(k);
}
void query(int l,int r,int k)
{
    if(t[k].sum==0)
        return;
    if(l==r)
    {
        b[ans]=t[k].sum;
        ans++;
        return;
    }
    int mid=M;
    pushdown(k);
    query(l,mid,lson);
    query(mid+1,r,rson);
}
int main()
{
    int i,j,n,m,l,r;
    ll s=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    sort(a+1,a+n+1,cmp);
    Build(1,n,1);
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&l,&r);
        update(l,r,1);
    }
    ans=0;
    query(1,n,1);
    sort(b,b+ans,cmp);
    for(i=1;i<=n&&i-1<ans;i++)
    {
        s+=(ll)a[i]*b[i-1];
    }
    printf("%lld\n",s);
    return 0;
}