FJWC2019 全连
Posted si--nian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FJWC2019 全连相关的知识,希望对你有一定的参考价值。
题目描述
有n个音符,第i个音符会在第i个时刻来临
令第 i 个音符的准备时间为 ti? 个单位时间,如果选择去点击第 i 个音符,那么就没法点击所有到来时刻在 (i−ti? ,i+ti?)中的音符。
每一个音符有一个权值,求一种点击方法使得权值和最高(N<=1e6)
Solution
首先先考虑最暴力的dp,令dp[i]表示我点到第i个时刻时,可以达到的最大权值
那么转移就很显然了
dp[i]=max(dp[j=1..i])+a[j](j+t[j]<=i&&i-t[i]>=j)
这个dp显然是O(n^2)的这时候我们发现每次循环1..i的过程十分的浪费时间所以我们来考虑优化这个过程
可以发现这是个二维偏序问题,一般的套路是一维排序另一维用数据结构去维护
因为i是递增的,这时候我们把所有的音符按照i+t[i]排序,并且用一个线段树维护区间内dp的最大值
为了满足j+t[j]<=i 我们在当前时刻>当前最小的i+t[i]的时候才把最小的i给modify进线段树里
每次查询的时候就只要查询1..i-t[i]的最大dp值然后只用最大dp值转移过来就可以了
这是一个O(N log N)的效率[因为评测姬跑的很快所以O(N log^2 N)跑过去了…]
Code
-
//考场代码...结果脑子一抽考场上用了堆维护第一维关系... 所以这个代码效率是O(N log^2 N)
-
#include <bits/stdc++.h>
-
#define pa pair<long long,long long>
-
using namespace std;
-
inline long long read(){
-
long long s=0,w=1;
-
char ch=getchar();
-
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)w=-1;ch=getchar();}
-
while(ch>=‘0‘&&ch<=‘9‘) s=s*10+ch-‘0‘,ch=getchar();
-
return s*w;
-
}
-
int N;
-
long long Tree[4005005];
-
void Change(int Now,int K,int l,int r,long long Ned)
-
{
-
int mid=(l+r)/2;
-
if (l==r&&l==K)
-
{
-
Tree[Now]=Ned;
-
return;
-
}
-
if (K<=mid)
-
Change(Now*2,K,l,mid,Ned);
-
if (mid<K)
-
Change(Now*2+1,K,mid+1,r,Ned);
-
Tree[Now]=max(Tree[Now*2],Tree[Now*2+1]);
-
}
-
long long query(int Now,int L,int R,int l,int r)
-
{
-
int mid=(l+r)/2;
-
if (L<=l&&r<=R)
-
return Tree[Now];
-
long long qwqq=0;
-
if (L<=mid)
-
qwqq=max(query(Now*2,L,R,l,mid),qwqq);
-
if (mid<R)
-
qwqq=max(query(Now*2+1,L,R,mid+1,r),qwqq);
-
return qwqq;
-
}
-
long long dp[1000005],a[1000005],t[1000005],Score[1000005];
-
priority_queue<pa,vector<pa>,greater<pa> > qwqq;
-
int main()
-
{
-
freopen("fc.in","r",stdin);
-
freopen("fc.out","w",stdout);
-
N=read();
-
for (int i=1;i<=N;i++)
-
t[i]=read();
-
for (int i=1;i<=N;i++)
-
a[i]=read();
-
for (int i=1;i<=N;i++)
-
Score[i]=a[i]*t[i];
-
for (int i=1;i<=N;i++)
-
{
-
pa r;
-
if (!qwqq.empty()) r=qwqq.top();
-
while (!qwqq.empty()&&r.first<=i)
-
{
-
Change(1,r.second,1,N,dp[r.second]);
-
qwqq.pop();
-
r=qwqq.top();
-
}
-
long long R=0;
-
if (i-t[i]>0)
-
R=query(1,1,i-t[i],1,N);
-
dp[i]=R+Score[i];
-
pa Now;
-
Now.first=i+t[i];
-
Now.second=i;
-
qwqq.push(Now);
-
}
-
long long ans=0;
-
for (int i=1;i<=N;i++)
-
ans=max(ans,dp[i]);
-
printf("%lld",ans);
-
return 0;
-
}
以上是关于FJWC2019 全连的主要内容,如果未能解决你的问题,请参考以下文章