题解:P10542 [THUPC2024] RPG
首先有一个比较显然的 dp:设
一个显然的发现是,对于所有
由于暴击规则只有
更新完
总时间复杂度
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) x*2
#define rs(x) x*2+1
#define mp make_pair
#define sec second
#define fir first
#define pii pair<int,int>
#define lowbit(i) i&-i
#define int long long
#define qingbai 666
using namespace std;
typedef long long ll;
const int N=2e5+5,S=(1<<20)+5,mo=1e9+7,inf=(ll)1e18+7;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int n,m,x,y;
int d[N],a[N],b[N];
struct rule{
int x,y,c;
}r[N];
int dp[N],cnt[N],upp;
vector<pii>atk[N],sit[N];
int maxs[N],maxa[N];
signed main(){
read(n),read(m),read(x),read(y),upp=sqrt(m);
rep(i,1,x)
read(d[i]);
rep(i,1,n)
read(a[i]),read(b[i]);
rep(i,1,m){
read(r[i].x),read(r[i].y),read(r[i].c);
cnt[r[i].y]++;
}
rep(i,1,m){
if(cnt[r[i].y]>upp)sit[r[i].x].push_back(mp(r[i].y,r[i].c));
else atk[r[i].y].push_back(mp(r[i].x,r[i].c));
}
rep(i,1,x)
maxa[i]=-inf;
rep(i,1,y)
maxs[i]=-inf;
rep(i,1,n){
dp[i]=dp[i-1]+d[b[i]];
if(cnt[b[i]]>upp)dp[i]=max(dp[i],maxa[b[i]]+d[b[i]]);
else{
for(auto j:atk[b[i]])
dp[i]=max(dp[i],maxs[j.fir]+j.sec+d[b[i]]);
}
maxs[a[i]]=max(maxs[a[i]],dp[i-1]);
for(auto j:sit[a[i]])
maxa[j.fir]=max(maxa[j.fir],dp[i-1]+j.sec);
}
printf("%lld\n",dp[n]);
return 0;
}