题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3872
题意:有n个龙珠按顺序放在一列,每个龙珠有一个type和一个权值,要求你把这n个龙珠分成k个段,每段的权值是这段中的最大的权值,使得最后的权值之和最小。但是现在有个要求,分的段中,龙珠的type不能和最右边的相等。
容易想到是一个DP:f[i]=Min{f[j]+Min(j,i) | j是满足要求的点}。直接搞的话O(n^2),显然超时了。但是可以发现,这个Min(j,i)是有分段性的,因此我们可以维护一个单调递减的栈,那么只要求栈中的元素就可以了,因为只有这些元素有效。这里还要求最小值,需要维护两课线段树,一颗是维护f[i]最小,还有一棵是f[j]+min(相对应的栈中的元素)。此题细节比较多,容易出错>,<,,,,也可能是我很久没刷题,残了T^T
1 //STATUS:C++_AC_1796MS_8848KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,102400000") 25 //using namespace __gnu_cxx; 26 //define 27 #define pii pair<int,int> 28 #define mem(a,b) memset(a,b,sizeof(a)) 29 #define lson l,mid,rt<<1 30 #define rson mid+1,r,rt<<1|1 31 #define PI acos(-1.0) 32 //typedef 33 typedef __int64 LL; 34 typedef unsigned __int64 ULL; 35 //const 36 const int N=100010; 37 const int INF=0x3f3f3f3f; 38 const int MOD=95041567,STA=8000010; 39 const LL LNF=1LL<<60; 40 const double EPS=1e-8; 41 const double OO=1e15; 42 const int dx[4]={-1,0,1,0}; 43 const int dy[4]={0,1,0,-1}; 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 45 //Daily Use ... 46 inline int sign(double x){return (x>EPS)-(x<-EPS);} 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 50 template<class T> inline T Min(T a,T b){return a<b?a:b;} 51 template<class T> inline T Max(T a,T b){return a>b?a:b;} 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 56 //End 57 58 LL low[N<<2][2],f[N]; 59 int l[N],la[N],q[N][2],type[N],eng[N]; 60 int T,n; 61 62 void update(int l,int r,int rt,int w,LL val,int flag) 63 { 64 if(l==r){ 65 low[rt][flag]=val; 66 return; 67 } 68 int mid=(l+r)>>1; 69 if(w<=mid)update(lson,w,val,flag); 70 else update(rson,w,val,flag); 71 low[rt][flag]=Min(low[rt<<1][flag],low[rt<<1|1][flag]); 72 } 73 74 LL query(int l,int r,int rt,int L,int R,int flag) 75 { 76 if(L<=l && r<=R){ 77 return low[rt][flag]; 78 } 79 int mid=(l+r)>>1; 80 LL ret=LNF; 81 if(L<=mid)ret=Min(ret,query(lson,L,R,flag)); 82 if(R>mid)ret=Min(ret,query(rson,L,R,flag)); 83 return ret; 84 } 85 86 int binary(int l,int r,int tar) 87 { 88 int mid; 89 while(l<r){ 90 mid=(l+r)>>1; 91 if(q[mid][0]<tar)l=mid+1; 92 else r=mid; 93 } 94 return l; 95 } 96 97 int main() 98 { 99 // freopen("in.txt","r",stdin); 100 int i,j,t,L,R,top; 101 LL lowf; 102 scanf("%d",&T); 103 while(T--) 104 { 105 scanf("%d",&n); 106 mem(la,0); 107 for(i=1;i<=n;i++){ 108 scanf("%d",&type[i]); 109 l[i]=la[type[i]]; 110 la[type[i]]=i; 111 } 112 for(i=1;i<=n;i++){ 113 scanf("%d",&eng[i]); 114 } 115 116 mem(low,INF);mem(f,INF);f[0]=0; 117 update(0,n+1,1,0,0,1); 118 q[top=0][0]=0;q[top][1]=INF; 119 for(i=1;i<=n;i++){ 120 while(q[top][1]<=eng[i]){ 121 update(0,n+1,1,q[top-1][0],LNF,0); 122 top--; 123 } 124 q[++top][0]=i;q[top][1]=eng[i]; 125 t=q[top-1][0]; 126 lowf=query(0,n+1,1,t,i-1,1); 127 update(0,n+1,1,t,lowf+eng[i],0); 128 129 L=binary(0,top+1,l[i]); 130 f[i]=query(0,n+1,1,q[L][0],i,0); 131 if(l[i]<q[L][0]){ 132 lowf=query(0,n+1,1,l[i],q[L][0]-1,1); 133 f[i]=Min(f[i],lowf+q[L][1]); 134 } 135 update(0,n+1,1,i,f[i],1); 136 } 137 138 printf("%I64d\n",f[n]); 139 } 140 return 0; 141 }