1. 程式人生 > >101889F Fundraising (二維帶權最長上升子序列)

101889F Fundraising (二維帶權最長上升子序列)

題意:二維帶權最長上升子序列。

解題思路:先對一維排序,然後在第二維做最長上升子序列的NlogN做法,同時維護好權值即可。記得離散化。

這裡相同的點最好合並一下,方便處理。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=200005;
typedef long long ll;

struct node{
    int A,B;
    ll C;
}P[MAXN];
bool cmp(node a,node b){
    if(a.A==b.A)
        return a.B<b.B;
    return a.A<b.A;
}

int s[MAXN*2];

vector<int> li[MAXN*2];

bool cmp2(int a,int b){
    return a>b;
}

map<pair<int,int> ,ll> C;

ll tree[MAXN];

int lowbit(int t)
{
    return t&(-t);
}

void update(int index,ll value){
    for(int i=index;i<=MAXN;i+=lowbit(i)){
        tree[i] = max(tree[i],value);
    }
}

ll sum(int index){
    ll sum = 0;
    for(int i=index;i>0;i-=lowbit(i)){
        sum = max(sum,tree[i]);
    }
    return sum;
}

int main(){
    
    int N;
    scanf("%d",&N);
    for(int i=0;i<N;i++){
        scanf("%d%d%lld",&P[i].A,&P[i].B,&P[i].C);
        s[i]=P[i].A;
        s[N+i]=P[i].B;
    }
    
    sort(s,s+2*N);
    int cnt=unique(s,s+2*N)-s;
    
    for(int i=0;i<N;i++){
        int a=lower_bound(s,s+cnt,P[i].A)-s+1;
        int b=lower_bound(s,s+cnt,P[i].B)-s+1;
        C[make_pair(a,b)]+=P[i].C;
        li[a].push_back(b);
        
    }
    
    for(int a=1;a<=cnt;a++){
        sort(li[a].begin(),li[a].end(),cmp2);
        for(int i=0;i<li[a].size();i++){
            auto b=li[a][i]; 
            ll tmp=sum(b-1);
            ll ans=tmp+C[make_pair(a,b)];
            update(b,ans);
        }
    }
    
    cout<<sum(cnt)<<endl;
    
    return 0;
}