【前言】
充满欺骗意味的题目。
【暴力】
记录每个羁绊是否出现,根据打法不同,复杂度亦不相同。
【比较厉害的暴力】
我们有一个稍微奇妙一点的做法。
用f[i]表示i与i+1到f[i]都建立了羁绊,可以发现f[i]具有单调性,那么在暴力的过程中,f[i]>=r则可以退出了。
这样的话可以优化不少,但还不够。
【正解】
我们还是用f[i]表示相同的东西,但这一次,我们用一些数据结构来维护区间最大值、最小值、区间和。
复杂度O(mlogn)
参考代码:
class Solution {
public:
/**
*
* @param n int整型
* @param m int整型
* @param a int整型二维数组
* @param aRowLen int a数组行数
* @param aColLen int* a数组列数
* @return long长整型vector
*/
long long ans;
long long f[300005*4][4];
vector<long>v;
void combine(int s)
{
f[s][0]=f[s+s][0]+f[s+s+1][0];
f[s][1]=max(f[s+s][1],f[s+s+1][1]);
f[s][3]=min(f[s+s][3],f[s+s+1][3]);
}
void build(int l,int r,int s)
{
if (l==r){
f[s][0]=l,f[s][1]=l,f[s][3]=l;
return;
}
build(l,(l+r)/2,s+s),build((l+r)/2+1,r,s+s+1);
combine(s);
}
void down(int l,int r,int s){
if (f[s][2]){
f[s][1]=f[s][2];
f[s][0]=f[s][2]*(r-l+1);
f[s][3]=f[s][2];
if (l!=r)
f[s+s][2]=f[s][2],f[s+s+1][2]=f[s][2];
f[s][2]=0;
}
}
void get(int l,int r,int s,int ll,int rr,int v){
down(l,r,s);
if (r<ll||rr<l)return;
if (f[s][3]>=v)return;
if (ll<=l&&r<=rr){
if (f[s][1]<=v){
f[s][2]=v;
ans+=(long long)v*(r-l+1)-f[s][0];
down(l,r,s);
return;
}
}
get(l,(l+r)/2,s+s,ll,rr,v),get((l+r)/2+1,r,s+s+1,ll,rr,v);
combine(s);
}
vector<long> wwork(int n, int m, int** a, int aRowLen, int* aColLen) {
// write code here
build(1,n,1);
int l,r;
for (int i=1;i<=m;i++)
{
l=a[i-1][0];
r=a[i-1][1];
ans=0;
get(1,n,1,l,r,r);
v.push_back(ans);
}
return v;
}
};
京公网安备 11010502036488号