C++ 优化还是新算法来解决这个问题?

C++ 优化还是新算法来解决这个问题?,c++,algorithm,data-structures,segment-tree,C++,Algorithm,Data Structures,Segment Tree,我正在努力解决这个问题: 小女孩有一个由n个元素组成的数组(数组中的元素从1开始索引) 此外,还有“q”查询,每个查询由一对整数li,ri(1)定义 ≤ 锂 ≤ ri ≤ n) 。您需要为每个查询找到索引从li到ri(包括li)的数组元素的总和 小女孩觉得这个问题很无聊。她决定在回复查询之前对数组元素重新排序,以使查询回复的总和达到最大可能。您的任务是找到此最大和的值 输入: 第一行包含两个空格分隔的整数n(1 ≤ N ≤ 10^5)和q(1 ≤ Q ≤ 10^5)-数组中的元素数和相应的查询

我正在努力解决这个问题:

小女孩有一个由n个元素组成的数组(数组中的元素从1开始索引)

此外,还有“q”查询,每个查询由一对整数li,ri(1)定义 ≤ 锂 ≤ ri ≤ n) 。您需要为每个查询找到索引从li到ri(包括li)的数组元素的总和

小女孩觉得这个问题很无聊。她决定在回复查询之前对数组元素重新排序,以使查询回复的总和达到最大可能。您的任务是找到此最大和的值


输入:

第一行包含两个空格分隔的整数n(1 ≤ N ≤ 10^5)和q(1 ≤ Q ≤ 10^5)-数组中的元素数和相应的查询数

下一行包含n个空格分隔的整数ai(1 ≤ 人工智能 ≤ 10^5)-数组元素

以下q行中的每一行都包含两个空格分隔的整数li和ri(1 ≤ 锂 ≤ ri ≤ n) -第i个查询


输出:

在单行中,打印单个整数-数组元素重新排序后查询答复的最大总和

Sample testcases:

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
我有段树的知识,所以我通过段树应用了延迟传播方法

我的努力代码:

#include <iostream>
#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <list>
#include <cmath>
#include <stack>
using namespace std;

#define scan(x) scanf("%d",&x)
#define print(x) printf("%d ",x)
#define println(x) printf("%d\n",x)
#define For(i,a,j,k) for (i = a; i < j; i+= k)
#define For_back(i,a,j,k) for (i = j; i >= a; i-= k)
#define SET(a,x) memset(a,x,sizeof(a))
#define mod 1000000007
#define inf 0x7fffffff
#define Max 2000000

typedef pair<int,int> pii;
typedef pair<pii,int> piii;

long long int tree[3*Max];
long long int lazy[3*Max];

void update(int node,int a,int b,int i,int j,long long int value)
{
    if (lazy[node]!= 0)
    {
        tree[node] += lazy[node];

        if (a != b)
        {
            lazy[2*node] += lazy[node];
            lazy[2*node+1] += lazy[node];
        }
        lazy[node] = 0;
    }
    if (a > b || a > j || b < i)
        return;
    if (a >= i && b <= j)
    {
        tree[node] += value;
        if (a != b)
        {
            lazy[2*node] += value;
            lazy[2*node+1] += value;
        }
        return;
    }
    int mid = (a+b)/2;
    update(2*node,a,mid,i,j,value);
    update(2*node+1,mid+1,b,i,j,value);

    tree[node] = (tree[2*node]+tree[2*node+1]);
}

long long int query(int node,int a,int b,int i,int j)
{
    if (a> b || a > j || b < i) return 0;

    if (lazy[node] != 0)
    {
        tree[node] += lazy[node];
        if (a != b)
        {
            lazy[2*node] += lazy[node];
            lazy[2*node+1] += lazy[node];
        }
        lazy[node] = 0;
    }
    if (a >= i && b <= j)
        return tree[node];
    int mid = (a+b)/2;
    long long int q1 = query(2*node,a,mid,i,j);
    long long int q2 = query(2*node+1,mid+1,b,i,j);

    return ((q1+q2));
}
int main()
{
    SET(lazy,0);
    SET(tree,0);

    int n,m;
    cin >> n >> m;
    int i,j;
    int arr[n];
    For(i,0,n,1)
    {
        cin >> arr[i];
    }
    sort(arr,arr+n);
    For(i,0,m,1)
    {
        long long int num1,num2;
        cin >> num1 >> num2;

        update(1,0,n-1,num1-1,num2-1,1);
    }
    long long int my[n];
    For(i,0,n,1)
    {   
        long long int number = query(1,0,n-1,i,i);       
        my[i] = number;
    }
    sort(my,my+n);
    long long int sum = 0;
    For_back(i,0,n-1,1){
        sum += my[i]*arr[i];
    }
    cout << sum << endl;
    return 0;   
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#定义扫描(x)scanf(“%d”、&x)
#定义打印(x)printf(“%d”,x)
#定义println(x)printf(“%d\n”,x)
#定义(i,a,j,k)为(i=a;i=a;i-=k)的返回(i,a,j,k)
#定义集合(a,x)memset(a,x,sizeof(a))
#定义mod 100000007
#定义inf 0x7fffffff
#定义最大2000000
typedef对pii;
typedef对piii;
长整型树[3*Max];
long-long-int-lazy[3*Max];
无效更新(int节点、int a、int b、int i、int j、long int值)
{
if(惰性[节点]!=0)
{
树[节点]+=惰性[节点];
如果(a!=b)
{
懒惰的[2*节点]+=懒惰的[node];
懒惰的[2*节点+1]+=懒惰的[node];
}
惰性[节点]=0;
}
如果(a>b | a>j | b=i&b b|a>j|b=i&b>n>>m;
int i,j;
int-arr[n];
对于(i,0,n,1)
{
cin>>arr[i];
}
排序(arr,arr+n);
对于(i,0,m,1)
{
长整数num1,num2;
cin>>num1>>num2;
更新(1,0,n-1,num1-1,num2-1,1);
}
long-long-int-my[n];
对于(i,0,n,1)
{   
长整数=查询(1,0,n-1,i,i);
我的[我]=号码;
}
排序(my,my+n);
长整型和=0;
对于_-back(i,0,n-1,1){
总和+=我的[i]*arr[i];
}

cout我认为这会起作用-请发表评论

创建一个名为count的维度n数组,并将其初始化为0 遍历Q数组

对于每个查询 -从li到ri递增计数1,即元素li到ri的计数 对数组n进行排序 对计数数组排序(记住索引) 选取计数中的最高值,并在相应的索引处放入N中的最高元素 对所有元素继续此操作


基本上,我们确保最高元素出现的次数最多(当被查询引用时)

我认为这会起作用-邀请评论

创建一个名为count的维度n数组,并将其初始化为0 遍历Q数组

对于每个查询 -从li到ri递增计数1,即元素li到ri的计数 对数组n进行排序 对计数数组排序(记住索引) 选取计数中的最高值,并在相应的索引处放入N中的最高元素 对所有元素继续此操作

基本上,我们确保最高元素出现的次数最多(当查询引用时)

这就是我要做的:

  • 创建了一个(散列)映射索引->计数。检查所有查询,并为范围内的每个索引增加计数(*)
  • 按大小、降序排列数组中的元素(现在称为
    values
    now)
  • 从hashmap中提取
    计数
    (索引现在无关紧要,因为我们不再需要它们,数组也会相应地重新排序),并对它们进行下位排序
  • 遍历计数的有序数组并求和
    sum+=计数[i]*值[i]
  • 假设您的数组是

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9
    
    查询如下:

    q1: 1-3
    q2: 2-4
    q3: 3-5
    
    地图:

    1->1
    2->2
    3->3
    4->2
    5->1
    
    已排序的计数:

    3,2,2,1
    
    一个完美的重新排序(与算法无关,因为只需要求和)

    查询总数:

    (6 + 7 + 9) + (7 + 9 + 8) + (9 + 8 + 5) = 68
    
    使用该算法:

    3 * 9 + 2 * 8 + 2 * 7 + 1 * 6 + 1 * 5 = 68
    
    (*)如果您想加快速度,可以使用大小为n的数组/向量,而不是映射,并使用索引作为键。如果在我的示例中提到映射,因为它使想法更加明显,我会这样做:

  • 创建了一个(散列)映射索引->计数。检查所有查询,并为范围内的每个索引增加计数(*)
  • 按大小、降序排列数组中的元素(现在称为
    values
    now)
  • 从hashmap中提取
    计数
    (索引现在无关紧要,因为我们不再需要它们,数组也会相应地重新排序),并对它们进行下位排序
  • 遍历计数的有序数组并求和
    sum+=计数[i]*值[i]
  • 假设您的数组是

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9
    
    查询如下:

    q1: 1-3
    q2: 2-4
    q3: 3-5
    
    地图:

    1->1
    2->2
    3->3
    4->2
    5->1
    
    已排序的计数:

    3,2,2,1
    
    一个完美的重新排序(与算法无关,因为只需要求和)

    查询总数:

    (6 + 7 + 9) + (7 + 9 + 8) + (9 + 8 + 5) = 68