P1552 [APIO2012]派遣(線段樹合併+二分)
線段樹合併板子題,維護子樹內薪水爲i的忍者有多少個,並記錄薪水的和。爲了使能被派遣的忍者更多,貪心取子樹內儘可能多的便宜忍者,線段樹上二分即可
直接線段樹合併可能會卡空間,離散化一下
線段樹合併的最後一層不能pushup!!!會變成0的,因此需要邊合併邊求和
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 100005 6 #define M1 N1*50 7 #define ll long long 8 using namespace std; 9 10 int n,S,tot,maxn; 11 int real[N1]; 12 struct node{ 13 int id,val; 14 bool operator < (const node &s2) const 15 { 16 if(val!=s2.val) return val<s2.val; 17 return id<s2.id; 18 } 19 }a[N1]; 20 21 struct Edge{ 22 int to[N1],nxt[N1],head[N1],cte; 23 void ae(int u,int v) 24 { 25 cte++; to[cte]=v, nxt[cte]=head[u]; 26 head[u]=cte; 27 } 28 }e; 29 struct SEGTREE{ 30 int ls[M1],rs[M1],sum[M1],root[N1],cnt; 31 ll cost[M1]; 32 void pushup(int rt) 33 { 34 sum[rt]=sum[ls[rt]]+sum[rs[rt]]; 35 cost[rt]=cost[ls[rt]]+cost[rs[rt]]; 36 } 37 void upd(int x,int l,int r,int &rt,int w) 38 { 39 if(!rt) rt=++cnt; 40 sum[rt]+=w, cost[rt]+=real[x]; 41 if(l==r) return; 42 // if(l==r) { sum[rt]+=w, cost[rt]+=x; return; } 43 int mid=(l+r)>>1; 44 if(x<=mid) upd(x,l,mid,ls[rt],w); 45 else upd(x,mid+1,r,rs[rt],w); 46 pushup(rt); 47 } 48 int mrg(int r1,int r2) 49 { 50 if(!r1||!r2) return r1+r2; 51 int rt=++cnt; 52 sum[rt]=sum[r1]+sum[r2]; 53 cost[rt]=cost[r1]+cost[r2]; 54 ls[rt]=mrg(ls[r1],ls[r2]); 55 rs[rt]=mrg(rs[r1],rs[r2]); 56 // pushup(rt); 57 return rt; 58 } 59 ll query(ll res,int l,int r,int rt) 60 { 61 if(res>=cost[rt]) return sum[rt]; 62 if(l==r) return 0; 63 int mid=(l+r)>>1; 64 if(res>=cost[ls[rt]]) return sum[ls[rt]]+query(res-cost[ls[rt]],mid+1,r,rs[rt]); 65 else return query(res,l,mid,ls[rt]); 66 } 67 }s; 68 69 int fa[N1],sal[N1],lea[N1]; 70 71 ll dfs(int u) 72 { 73 int j,v; ll ans=0; 74 s.upd(sal[u],1,maxn,s.root[u],1); 75 for(j=e.head[u];j;j=e.nxt[j]) 76 { 77 v=e.to[j]; if(v==fa[u]) continue; 78 ans=max(ans,dfs(v)); 79 s.root[u]=s.mrg(s.root[u],s.root[v]); 80 } 81 ans=max(ans,1ll*lea[u]*s.query(tot,1,maxn,s.root[u])); 82 return ans; 83 } 84 int main() 85 { 86 // freopen("a.txt","r",stdin); 87 scanf("%d%d",&n,&tot); 88 for(int i=1;i<=n;i++) 89 { 90 scanf("%d%d%d",&fa[i],&sal[i],&lea[i]); 91 if(fa[i]) e.ae(fa[i],i); 92 else S=i; 93 a[i]=(node){i,sal[i]}; 94 } 95 sort(a+1,a+n+1); 96 maxn=1; 97 for(int i=1;i<=n;i++) 98 { 99 if(a[i].val!=a[i-1].val) maxn++, real[maxn]=a[i].val; 100 sal[a[i].id]=maxn; 101 } 102 ll ans=dfs(S); 103 printf("%lld\n",ans); 104 return 0; 105 }
#273 DNA序列 (DP)
設計DP,f[i][j]表示第一個串匹配到第i位,第二個串匹配到j位時的最大匹配值
然而連續空格的負貢獻會減少,容易想到分三種情況討論,所以加一維記錄
f[i][j][0/1/2]分別表示兩個串分別匹配到i,j時,最後一個位置是 x x // x _ // _ x 時的答案 (x是字母,_是空格)
轉移方程很水,注意得賦初始值,但還不能直接memset,會T..
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 3040 6 #define inf 0x3f3f3f3f 7 #define ll long long 8 using namespace std; 9 10 char str1[N1],str2[N1]; 11 int a[N1],b[N1],w[4][4],f[N1][N1][3]; 12 int n,m,A,B; 13 int idx(char c) 14 { 15 if(c=='A') return 0; 16 if(c=='T') return 1; 17 if(c=='G') return 2; 18 if(c=='C') return 3; 19 return -1; 20 } 21 22 int main() 23 { 24 // freopen("a.txt","r",stdin); 25 int i,j,k; 26 scanf("%s",str1+1); n=strlen(str1+1); 27 for(i=1;i<=n;i++) a[i]=idx(str1[i]); 28 scanf("%s",str2+1); m=strlen(str2+1); 29 for(i=1;i<=m;i++) b[i]=idx(str2[i]); 30 for(i=0;i<4;i++) for(j=0;j<4;j++) scanf("%d",&w[i][j]); 31 scanf("%d%d",&A,&B); 32 //memset(f,-0x3f,sizeof(f)); 33 f[0][0][0]=0; f[0][0][1]=f[0][0][2]=-inf; 34 for(i=0;i<=n;i++) 35 { 36 for(j=0;j<=m;j++) 37 { 38 if(!i&&!j) continue; 39 f[i][j][0]=f[i][j][1]=f[i][j][2]=-inf; 40 if(i>0 && j>0) 41 for(k=0;k<=2;k++) //x x 42 f[i][j][0]=max(f[i][j][0], f[i-1][j-1][k]+w[a[i]][b[j]] ); 43 44 //x _ 45 if(i>0) 46 { 47 f[i][j][1]=max(f[i][j][1], f[i-1][j][0]-A ); 48 f[i][j][1]=max(f[i][j][1], f[i-1][j][1]-B ); 49 f[i][j][1]=max(f[i][j][1], f[i-1][j][2]-A ); 50 } 51 52 //_ x 53 if(j>0) 54 { 55 f[i][j][2]=max(f[i][j][2], f[i][j-1][0]-A ); 56 f[i][j][2]=max(f[i][j][2], f[i][j-1][1]-A ); 57 f[i][j][2]=max(f[i][j][2], f[i][j-1][2]-B ); 58 } 59 } 60 } 61 int ans=-inf; 62 ans=max(ans,f[n][m][0]); ans=max(ans,f[n][m][1]); ans=max(ans,f[n][m][2]); 63 printf("%d\n",ans); 64 return 0; 65 }