CF1452E Two Editorials

这是一道反问题。

如果给你具体的两个author的区间,你就可以算出∑ai,现在是不告诉你author的区间,该如何选能使得总和最大。

许多出题人都喜欢出反问题,我感觉思考反问题也挺好玩的。

首先,这两个author应该是为了加强难度设置的,我们应该先考虑一个author的情况。

如果一个位置被x次区间覆盖,那么就设置数值为x,这样就等于找一个长度为k的区间使得区间和最大。

这很简单,先差分来对每个数字算出x,然后直接扫一遍。

现在有两个author,就涉及了max的问题。瞬间难度迷雾了起来。

 

看了题解,发现我只不过是没等到可以颠覆你一切思路的program的出现。

 

关键在于,对于一个区间[L,R],一个author区间,不断移动,可以发现当author区间的中点与区间[L,R]中点重合的时候,区间[L,R]被覆盖的长度是最大的。

因此,如果有两个author区间,区间中点离被覆盖区间中点的距离最近的那个才是发挥作用的区间。

因此,被覆盖的区间,被谁覆盖,是连续的分明的两段。

这就是二分所需要的单调性。

我们枚举这个分界点,然后在各自界内,独立地找出author的最优解,这部分可以预处理。

 

写了一半的代码:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,n) for (int i=1;i<=n;i++)
#define REP(i,a,b) for (int i=a;i<=b;i++)
 
#define pb push_back
#define fi first
#define se second
#define pi pair<int,int>
#define mp make_pair
 
typedef long long ll;
typedef complex<double> comp;
 
const int inf=0x3f3f3f3f;
const ll linf=1e18;
const int N=5e5+10;
const double eps=1e-10;
const ll mo=1e9+7;

int n,m;
int k;
int l[N],r[N];
int a[N];
int f[N],g[N];
int ans;
struct node {
    int l,r;
} b[N];
bool cmp(node x,node y) {
    double xm=0.5*(x.l+x.r),ym=0.5*(y.l+y.r);
    return xm<ym;
}
int main() {
 
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n>>m>>k;
    FOR(i,m) {
        cin>>l[i]>>r[i];
        a[l[i]]++;
        a[r[i]+1]--;
        b[i].l=l[i],b[i].r=r[i];
    }
    sort(b+1,b+1+n,cmp);
    FOR(i,n) l[i]=b[i].l,r[i]=b[i].r;
    FOR(i,n) a[i]+=a[i-1];
    REP(i,k,n) f[i]=max(f[i-1],a[i]-a[i-k]);
    for (int i=n-k+1;i>=1;i--) g[i]=max(g[i+1],a[i+k-1]-a[i-1]);
    int p=1;
    REP(i,k+1,(n+n-k+1)) {
        double j=0.5*i;
        while (0.5*(l[p]+r[p])<=j) {
            p++;
        }
        
    }
    return 0;
}

  

posted @ 2021-03-07 20:51  AngelKnows  阅读(65)  评论(0)    收藏  举报