1. 程式人生 > >Wannafly挑戰賽21 C 大水題

Wannafly挑戰賽21 C 大水題

整型 des 水題 都是 -c 前綴和 cli 接下來 copy

題目描述

現在給你N個正整數ai,每個數給出一“好數程度” gi(數值相同但位置不同的數之間可能有不同的好數程度)。對於在 i 位置的數,如果有一在j位置的數滿足 j < i 且 ai=aj,則你可以將位於[i,j]閉區間內的序列評為“好序列”,然後獲得∑gk(j≤k≤i)(此閉區間內“好數程度”之和)分數。 註意: 在所有情況下,每個數都只能被一個”好序列”包含(只能與其他相應數被評為”好序列”一次);在符合要求的情況下,”好序列”的評定次數不受限制,且通過不同”好序列”獲得的分數可以累加。

輸入描述:

第一行有一個正整數N。
接下來的一行有N個正整數ai,表示意義如上。
(保證ai在32位整型範圍內)
接下來的一行有N個正整數gi,表示ai的”好數程度”。
(保證gi在64位整型範圍內)

輸出描述:

一個整數,你可以獲得的最大分數(通過不同”好序列”獲得的分數可以累加),保證答案在64位整型範圍內。
示例1

輸入

復制
7
1 2 1 2 3 2 3
1 4 3 4 3 4 5

輸出

復制
23

備註:

數據範圍 2≤N≤300000




 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <string>
 7
#include <deque> 8 #include <map> 9 using namespace std; 10 #define ll long long 11 #define N 300008 12 #define gep(i,a,b) for(int i=a;i<=b;i++) 13 #define gepp(i,a,b) for(int i=a;i>=b;i--) 14 #define gep1(i,a,b) for(ll i=a;i<=b;i++) 15 #define gepp1(i,a,b) for(ll i=a;i>=b;i--) 16
#define mem(a,b) memset(a,b,sizeof(a)) 17 ll sum[N],g[N],dp[N]; 18 int a[N],pre[N]; 19 int n; 20 map<int,int>mp; 21 int main() 22 { 23 scanf("%d",&n); 24 gep(i,1,n) 25 { 26 scanf("%d",&a[i]); 27 pre[i]=mp[a[i]];//記錄前面a[i]==a[j]的j的位置 28 mp[a[i]]=i; 29 } 30 gep(i,1,n){ 31 scanf("%lld",&g[i]); 32 sum[i]=sum[i-1]+g[i];//前綴和 33 } 34 int j; 35 gep(i,2,n){ 36 dp[i]=dp[i-1];//初始化為dp[i-1] 37 j=pre[i]; 38 while(j){ 39 dp[i]=max(dp[i],sum[i]-sum[j-1]+dp[j-1]);//每個數只能用一次 40 if(dp[i]==sum[i]) break;//一定最大了,不然會超時 41 j=pre[j];//前面的j都是可能的 42 } 43 } 44 printf("%lld\n",dp[n]); 45 return 0; 46 }

Wannafly挑戰賽21 C 大水題