根据题目意思可以得知,按照某个数字被加的次数排序,然后从大往小乘即可。
那么,问题转化为两个部分:1、区间修改+单点查询
2、排序
看数据范围:n 对应 2E5 m 对应 2E5,开线段树,维护和值,进行区间更新,复杂度 nlogn
然后,单点查询所有点的值,复杂度 nlogn
之后,排序,复杂度 nlogn
最后,循环求和输出,复杂度 n
可以得知,复杂度 O(nlogn),问题可以解决。
注:我没有用排序,直接使用降序优先队列,复杂度nlogn,AC代码如下:
#include<bits/stdc++.h>
#define MAXN 200010 //今天RE了一次,就是因为平时习惯1E5 + 5,没注意到本题的 2E5
#define inf 0x3f3f3f3f
using namespace std;
priority_queue <int,vector<int>,less<int> > q;
struct node{
int l,r;//区间[l,r]
int add;//区间的延时标记
int sum;//区间和
}tree[MAXN<<2];//一定要开到4倍多的空间
void pushup(int index){
tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
}
void pushdown(int index){
if(tree[index].add){
tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].add += tree[index].add;
tree[index<<1|1].add += tree[index].add;
tree[index].add = 0;
}
}
void build(int l,int r,int index){
tree[index].l = l;
tree[index].r = r;
tree[index].add = 0;//刚开始一定要清0
if(l == r){
tree[index].sum = 0;
return ;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
void updata(int l,int r,int index,int val){
if(l <= tree[index].l && r >= tree[index].r){
tree[index].sum += (tree[index].r-tree[index].l+1)*val;
tree[index].add += val;//延时标记
return ;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
if(l <= mid){
updata(l,r,index<<1,val);
}
if(r > mid){
updata(l,r,index<<1|1,val);
}
pushup(index);
}
int query(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].sum;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
ans += query(l,r,index<<1);
}
if(r > mid){
ans += query(l,r,index<<1|1);
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1); //建树时全部给0
for(int i = 0;i < m;i++){
int l,r;
cin>>l>>r;
updata(l,r,1,1);
}
for(int i = 1;i <= n;i++){
int r = query(i,i,1);
q.push(r);
}
long long ans = 0;
long long r1 = n;
while(!q.empty()){
long long t = q.top();
ans += t * r1--;
q.pop();
if(t == 0) break; //一个很小的优化
}
cout<<ans<<endl;
return 0;
}如有意见建议,欢迎联系2339814485(QQ),注明来意即可。

京公网安备 11010502036488号