竞赛讨论区 > B题 nlognlog^2(max{val}) 做法
头像
zlc1114
编辑于 2018-07-28 21:05
+ 关注

B题 nlognlog^2(max{val}) 做法

我的做法和题解的做法不一样。我看到sum{n}<=20000就以为不能平方的做法。
然后我的做法如下:
首先将所有区间排序,考虑二分答案
然后观察到,每个点只会被最多两个区间覆盖到,那么考虑某个区间时,不妨考虑后半段两个区间没有重合的地方
对于每个区间来说,和之前的区间可能会重合,可能不会重合,我们分开考虑
比如区间l,r,权值是val,此时二分的答案是x
那我们就要再l->r中找到一个区间l'->r',val'(r'在l-1->r内,l在l'->r'内),使得r'最小,而且满足val'+val<=x
那也就是l->r内的r',val'小于x-val的最小r'是多少
这个东西我树套树维护了一下,总复杂度树套树两个log加上二分答案一个log,其中树套树可以用bit套线段树(我是线段树套线段树)
#include <sstream>
#include <fstream>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <utility>
#include <cassert>
#include <bitset>
using namespace std;
#define REP(I,N) for (I=0;I<N;I++)
#define rREP(I,N) for (I=N-1;I>=0;I--)
#define rep(I,S,N) for (I=S;I<N;I++)
#define rrep(I,S,N) for (I=N-1;I>=S;I--)
#define FOR(I,S,N) for (I=S;I<=N;I++)
#define rFOR(I,S,N) for (I=N;I>=S;I--)

#define DEBUG
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define deputs(str) fprintf(stderr, "%s\n",str)
#else
#define debug(...)
#define deputs(str)
#endif // DEBUG
typedef unsigned long long ULL;
typedef unsigned long long ull;
typedef long long LL;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fll;
const LL M=1e9+7;
const LL maxn=2000+7;
const double pi=acos(-1.0);
const double eps=0.0000000001;
LL gcd(LL a, LL b) {return b?gcd(b,a%b):a;}
template<typename T>inline void pr2(T x,int k=64) {ll i; REP(i,k) debug("%d",(x>>i)&1); putchar(' ');}
template<typename T>inline void add_(T &A,int B) {A+=B; (A>=M) &&(A-=M);}
template<typename T>inline void mul_(T &A,ll B) {(A*=B)%=M;}
template<typename T>inline void mod_(T &A,ll B=M) {A%=M;}
template<typename T>inline void max_(T &A,T B) {(A<B) &&(A=B);}
template<typename T>inline void min_(T &A,T B) {(A>B) &&(A=B);}
template<typename T>inline T abs(T a) {return a>0?a:-a;}
template<typename T>inline T powMM(T a, T b) {
    T ret=1;
    for (; b; b>>=1ll,a=(LL)a*a%M)
        if (b&1) ret=(LL)ret*a%M;
    return ret;
}
int n,m,q;
char str[maxn];
int TaskA();
void Task_one() {TaskA();}
void Task_T() {int T; scanf("%d",&T); while (T--) TaskA();}
void Task_more_n() {while (~scanf("%d",&n)) TaskA();}
void Task_more_n_m() {while (~scanf("%d%d",&n,&m)) TaskA();}
void Task_more_n_m_q() {while (~scanf("%d%d%d",&n,&m,&q)) TaskA();}
void Task_more_string() {while (~scanf("%s",str)) TaskA();}

struct node{
    int l,r,min;
    node(){l=r=0;min=INF;}
}T[maxn*200]; int tot=0;
int root[maxn*4];
void Update(int &x,int val,int r,int L,int R){
    if (!x) x=++tot,T[x]=node(); min_(T[x].min,r);
    if (L==R) return;
    int mid=(L+R)/2;
    if (val<=mid) Update(T[x].l,val,r,L,mid);
    else Update(T[x].r,val,r,mid+1,R);
}
void update(int x,int l,int r,int val,int L,int R){
    if (l<=L&&R<=r) {Update(root[x],val,r,0,2000); return;}
    int mid=(L+R)/2;
    if (l<=mid) update(x<<1,l,r,val,L,mid);
    if (mid<r) update(x<<1|1,l,r,val,mid+1,R);
}
int Query(int x,int pos,int L,int R){
    if (!x) return INF;
    if (R<=pos) return T[x].min;
    int ret=INF,mid=(L+R)/2;
    min_(ret,Query(T[x].l,pos,L,mid));
    if (mid<pos) min_(ret,Query(T[x].r,pos,mid+1,R));
    return ret;
}
int query(int x,int pos,int val,int L,int R){
    int ret=Query(root[x],val,0,2000);
    if (L==R) return ret;
    int mid=(L+R)/2;
    if (pos<=mid) min_(ret,query(x<<1,pos,val,L,mid));
    if (mid<pos) min_(ret,query(x<<1|1,pos,val,mid+1,R));
    return ret;
}
vector<pii> things[maxn];
bool solve(int x){
    tot=0; int i;
    FOR(i,1,(n+1)*4) root[i]=0;
    update(1,0,0,0,0,n);
    FOR(i,1,n){
        for (auto now:things[i]){
            int r=query(1,now.first-1,x-now.second,0,n);
            if (r+1<=i) {
                update(1,r+1,i,now.second,0,n);
                update(1,i,i,0,0,n);
            }
        }
    }
    if (query(1,n,x,0,n)==n) return true;
    return false;
}
int TaskA() {
    int i;
    scanf("%d%d",&m,&n);
    FOR(i,1,n) things[i].clear();
    FOR(i,1,m){
        int l,r,val;
        scanf("%d%d%d",&l,&r,&val);
        things[r].push_back(make_pair(l,val));
    }
    int l,r;
    l=0;r=2000+7;
    while (l+1<r) {
        int mid=(l+r)/2;
        if (solve(mid)) r=mid;
        else l=mid;
    }if (r==2007) puts("-1");
    else printf("%d\n",r);
    return 0;
}
void initialize() {}
int main() {
    int startTime=clock();
    //initialize
    initialize();
    debug("/--- initializeTime: %ld milliseconds ---/\n",clock()-startTime);
    Task_T();
}

全部评论

(1) 回帖
加载中...
话题 回帖

等你来战

查看全部

热门推荐