[X]$Mr.Young's\ Picture\ Permutations$
前面这儿写了挺多道辣,,,懒得写辣$QAQ$
(后面所有同上都是同这个$QwQ$
[X]$LCIS$
做过了,看这儿
$upd$:,,,这题有猫饼,不呲呲快读,用快读会$T$一个点,,,然后我下了数据下来发现明明是数据的锅,,,?我感觉它给我的这个数据明明就不够,,,?但反正我改成$scanf$或者$cin$就过去了,,,什么$sd$玩意$QAQ$
[X]$Mobile\ Service$
无脑$dp$入门题,,,?
设$f_{i,j,k}$表示时间$i$没站在$d_{i}$的两个人的坐标,然后只要记得判下说任意俩人不能站在同一个位置就欧克,,,$QwQ$
然后$i$显然是不需要的只是为了方便表述设的这一维,,,实际$code$中是不会有这一维的昂$QwQ$
哦话说,这样儿说着很简单,其实好像是要证个东西,,,就三个人的坐标一定都是移动到$d_{i}$,不可能移动到别的位置,,,$umm$过于显然不证了,,,只是$cue$下其实是要证这个东西的来着$QAQ$
嗷还有一个就,这个$i$显然是要滚掉的嘛,正常方法应该就滚成[0/1]就欧克,然后因为$gql$没有脑子,就直接暴力开了个$f$再开了个$g$,当然显然的是开[0/1]还是好写,因为可以用$memset$,常数应该会小些,,,?不过麻油关系反正过得去就成$bushi$
$over$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int L=200+10,N=1000+10; int l,n,f[N][N],g[N][N],pos[L],cst[L][L],as; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } int main() { freopen("5102.in","r",stdin);freopen("5102.out","w",stdout); l=read();n=read()+3;rp(i,1,l)rp(j,1,l)cst[i][j]=read();pos[1]=1;pos[2]=2;pos[3]=3;memset(f,63,sizeof(f));as=f[0][0];f[1][2]=f[2][1]=0; rp(i,4,n) { pos[i]=read();rp(j,1,l)rp(k,1,l)g[j][k]=f[j][k],f[j][k]=f[0][0]; rp(j,1,l) rp(k,1,l) { if(j==k)continue; if(k!=pos[i] && pos[i-1]!=pos[i])f[k][pos[i-1]]=f[pos[i-1]][k]=min(f[k][pos[i-1]],g[j][k]+cst[j][pos[i]]); if(j!=pos[i] && pos[i-1]!=pos[i])f[j][pos[i-1]]=f[pos[i-1]][j]=min(f[j][pos[i-1]],g[j][k]+cst[k][pos[i]]); if(j!=pos[i] && k!=pos[i])f[j][k]=f[k][j]=min(f[j][k],g[j][k]+cst[pos[i-1]][pos[i]]); } } rp(i,1,l)rp(j,1,l)if(i!=j && pos[n]!=i && pos[n]!=j)as=min(as,f[i][j]);printf("%d\n",as); return 0; }
[X]$Making\ the\ Grade$
做过辣,看这儿
[X]传纸条
又双叒是个$dp$无脑入门题,,,?
首先四维$dp$过于显然不想写了,,,
然后考虑四位压成三维,依然太显然了,,,不写辣/$kel\ kel\ kel$
反正大致思路就上面这样儿的,懒得写了$over$
对了,这个$code$是我去年9月份写的了(,,,我那个时候做的题居然这么水,,,?太菜了嘤嘤嘤),,,所以贼丑但我也懒得改了$QAQ$
View Code#include<bits/stdc++.h> using namespace std; int a[55][55]; int f[110][55][55]; int read() { char ch; int x=0; bool o=0; ch=getchar(); while(ch!='-' && (ch<'0' || ch>'9'))ch=getchar(); if(ch=='-')o=1; while(ch>='0' && ch<='9') { x=(x<<3)+(x<<1)+(ch^'0'); ch=getchar(); } if(o==1)return -x; return x; } int main() { int m,n; m=read(); n=read(); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++)a[i][j]=read(); memset(f,-1,sizeof(f)); f[2][1][1]=0; for(int k=3;k<m+n;k++) for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { f[k][i][j]=max(f[k][i][j],max(f[k-1][i][j],max(f[k-1][i-1][j],max(f[k-1][i][j-1],f[k-1][i-1][j-1]))))+a[k-i][i]+a[k-j][j]; if(f[k][i][j]==a[k-i][i]+a[k-j][j]-1)f[k][i][j]=-1; } printf("%d",f[m+n-1][n-1][n]); return 0; }
[X]$I-country$
比起前面几题的话,相对而言还是比较有趣的辣,,,?
$so$大概港下$QwQ$
首先考虑怎么设状态?
首先理解下题意昂,这个所谓凸壳,其实就说要求左端点先递减后递增,右端点先递增后递减
于是显然就考虑状态为$f_{i,j,l,r,0/1,0/1}$,表示选到第$i$行,选了$j$个,左端点到$l$,右端点到$r$,左端点递增递减状态,右端点递增递减状态
转移,表述比较麻烦但并不难想,,,?就先不写辣$QwQ$
欧克然后就做完了,,,然而因为$gql$过于傻逼所以依然$WA$了$inf$次,,,我要死了呜呜呜
想提两个要注意的点$QwQ$
第一个是说,要考虑到可能存在前面若干行不选和后面若干行不选这样儿的情况(像我就非常,没有脑子,直接就又多$for$了下就非常暴力地搞掉了$QwQ$
第二个是说,要注意到还有个隐藏条件,就是相邻两行之间必须有交点,,,记得判下不然会被#4给搞掉应该$QAQ$
嗷还有就是我没写怎么记录方案,,,比较正常的想法应该就过程中瞎搞下应该就欧克了,,,?
然后因为$gql$没有脑子,,,打完才想起来要记录方案,,,然后就懒得瞎搞了,直接在结尾非常暴力地搞了一通,$over$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=15+10,K=250; int n,m,kk,dat[N][N],f[N][K][N][N][2][2],sum[N][N],as,prel,prer,opl,opr,tmpn; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } signed main() { // freopen("5104.in","r",stdin);freopen("5104.out","w",stdout); n=read();m=read();kk=read();rp(i,1,n)rp(j,1,m)sum[i][j]=sum[i][j-1]+(dat[i][j]=read()); rp(i,1,n) rp(j,1,min(m*i,kk)) rp(l,1,m) rp(r,l,m) { if(j<r-l+1)continue; f[i][j][l][r][0][0]=f[i][j][l][r][0][1]=f[i][j][l][r][1][0]=f[i][j][l][r][1][1]=sum[i][r]-sum[i][l-1]; if(i==1) { if(j!=r-l+1)f[i][j][l][r][0][0]=f[i][j][l][r][0][1]=f[i][j][l][r][1][0]=f[i][j][l][r][1][1]=0; continue; } rp(ll,1,r) rp(rr,l,m) { if(j<rr-ll+1+r-l+1)continue;if(ll>r || l>rr)continue; if(ll>=l) { if(rr>=r)f[i][j][l][r][0][0]=max(max(f[i-1][j-(r-l+1)][ll][rr][0][0],f[i-1][j-(r-l+1)][ll][rr][0][1])+sum[i][r]-sum[i][l-1],f[i][j][l][r][0][0]); if(rr<=r)f[i][j][l][r][0][1]=max(f[i-1][j-(r-l+1)][ll][rr][0][1]+sum[i][r]-sum[i][l-1],f[i][j][l][r][0][1]); } if(ll<=l) { if(rr>=r)f[i][j][l][r][1][0]=max(max(max(f[i-1][j-(r-l+1)][ll][rr][1][0],f[i-1][j-(r-l+1)][ll][rr][1][1]),max(f[i-1][j-(r-l+1)][ll][rr][0][0],f[i-1][j-(r-l+1)][ll][rr][0][1]))+sum[i][r]-sum[i][l-1],f[i][j][l][r][1][0]); if(rr<=r)f[i][j][l][r][1][1]=max(max(f[i-1][j-(r-l+1)][ll][rr][0][1],f[i-1][j-(r-l+1)][ll][rr][1][1])+sum[i][r]-sum[i][l-1],f[i][j][l][r][1][1]); } } } rp(i,1,n)rp(l,1,m)rp(r,l-1,m){ri tmp=as;as=max(as,max(max(f[i][kk][l][r][0][0],f[i][kk][l][r][0][1]),max(f[i][kk][l][r][1][0],f[i][kk][l][r][1][1])));if(tmp!=as)tmpn=i;} printf("Oil : %lld\n",as); n=tmpn; rp(l,1,m) rp(r,l,m) { if(f[n][kk][l][r][0][0]==as){prel=l,prer=r,opl=0,opr=0;as-=sum[n][r]-sum[n][l-1];kk-=r-l+1;l=m+1;break;} if(f[n][kk][l][r][0][1]==as){prel=l,prer=r,opl=0,opr=1;as-=sum[n][r]-sum[n][l-1];kk-=r-l+1;l=m+1;break;} if(f[n][kk][l][r][1][0]==as){prel=l,prer=r,opl=1,opr=0;as-=sum[n][r]-sum[n][l-1];kk-=r-l+1;l=m+1;break;} if(f[n][kk][l][r][1][1]==as){prel=l,prer=r,opl=1,opr=1;as-=sum[n][r]-sum[n][l-1];kk-=r-l+1;l=m+1;break;} } rp(i,prel,prer)printf("%lld %lld\n",n,i); my(i,n-1,1) rp(l,1,m) rp(r,l,m) { if(opl && prel<l)continue;if(!opl && prel>l)continue;if(opr && prer<r)continue;if(!opr && prer>r)continue;if(prel>r || l>prer)continue; if(f[i][kk][l][r][0][0]==as) if(!opr) { as-=sum[i][r]-sum[i][l-1];prel=l,prer=r,opl=0,opr=0;kk-=r-l+1;l=m+1;r=m+1; rp(p,prel,prer)printf("%lld %lld\n",i,p);continue; } if(f[i][kk][l][r][0][1]==as) { as-=sum[i][r]-sum[i][l-1];prel=l,prer=r,opl=0,opr=1;kk-=r-l+1;l=m+1;r=m+1; rp(p,prel,prer)printf("%lld %lld\n",i,p);continue; } if(f[i][kk][l][r][1][0]==as) if(opl && !opr) { as-=sum[i][r]-sum[i][l-1];prel=l,prer=r,opl=1,opr=0;kk-=r-l+1;l=m+1;r=m+1; rp(p,prel,prer)printf("%lld %lld\n",i,p);continue; } if(f[i][kk][l][r][1][1]==as) if(opl) { as-=sum[i][r]-sum[i][l-1];prel=l,prer=r,opl=1,opr=1;kk-=r-l+1;l=m+1;r=m+1; rp(p,prel,prer)printf("%lld %lld\n",i,p);continue; } } return 0; } /* 0:递减 1:递增 l:先0后1 r:先1后0 0<-0/1 1<-1 1<-0/1 0<-0 */
[X]$Cookies$
这题挺有趣的,,,就这题和之前做过的一道题有点儿像,,,这个,虽然是道绿但我印象还挺深的,,,因为它是这样儿的,就,有一部分之间是无后效性的,但有一部分是有后效性的,,,
这题也是,首先要想到,显然从多往少安排,所以这时候显然有个小小的贪心,就说$g_{i}$越大的拿到的饼干数越多,于是就先按$g_{i}$排个序,然后考虑设$f_{i,j,k}$表示分到第$i$个孩子了,然后分了$j$个饼干,这一个孩子拿了$k$个饼干,看数据范围,发现$O(NM^{2})$,就不太星$QAQ$
好然后再仔细思考下,假如现在有$m$块,显然先平均分,每人拿到$\left \lfloor \frac{m}{n} \right \rfloor$块,这样儿就能把$m$控制在$n$范围以内,就过辣!
然后就被$hack$辣嘤嘤嘤
来我先$hack$下我的无脑优化想法$QAQ$
比如有5个,分别是$inf,inf,inf,inf,0$,然后有13块饼干
如果先贪心,就先均分,每人2个,剩3个,然后这时候$dp$下,显然是前三个每人拿一个,然后代价就是$3\cdot inf$
但是正解应该是,前四个人每人拿3个,然后最后一个人拿1个,这样儿代价就是0,,,
所以就被$hack$了\$kel\ kel\ kel$
而且上面这个还有个问题在于,可以有相等的,就会导致并不知道到底有多少个比它大的$qwq$
好然后现在整个儿都被$hack$了嘤嘤嘤,,,
重写下解法嘤嘤嘤
这里要考虑,状态缩放,也就是通过等价交换使得时间复杂度变好看
先用下万能的分类讨论法$QwQ$
对了先说下,$i$表示的是第$i$个人,$j$表示的是分了$j$块饼干,$k$表示的是从第$k$个人开始所有人都只有1块
1)第$i$个人获得的饼干数>1
这个可以等价与分配$j-i$个饼干给前$i$个人,每人少拿一块,这个显然是等价的$QwQ$,因为相对大小是不变的(这个就和前面那个均分有点儿像,,,是不是$QwQ$
这样儿转移就可以变成,$f_{i,j}=f_{i-1,j-i}$
2)第$i$个人获得的饼干数=1
直接考虑在它及之前有多少个人只有1块?
这样儿转移就可以变成$f_{i,j}=(f_{k,j-(i-k)}+k\cdot \sum_{p=k+1}^{i}g_{p})_{min}$
综上,转移就是$f_{i,j}=(f_{i-1,j-i},(f_{k,j-(i-k)}+k\cdot \sum_{p=k+1}^{i}g_{p})_{min})_{min}$
就做完啦啦啦啦
昂然后最后输出方案,其实我$jio$得还挺有趣的,但我是瞎搞一通搞出来的,也说不出个什么所以然来,就瞎递归下然后模拟($bushi$下就瞎搞出来了,,,所以具体看$code$趴$QAQ$
嗷对了,,,$gql$在线傻逼了一通,,,大概港下$gql$的$sd$想法昂$QAQ$
是这样儿的,就,假如现在是在进行,$i=1$的枚举$k$的转移,然后假如我在转移到$k$的时候,实际上的那个$f_{k,j-(i-k)}$的那个点也是从$k=1$转移来的,那就会导致$f_{i,j}$变大鸭(就因为本来没有$k$个大于1的,但这儿当做有$k$个了嘛$QwQ$
然后仔细一想发现显然是我傻逼了,,,因为如果有这种情况,我一定吃枣会枚举到$k=1$转移来的点${k}'$,然后就一定会从${k}'$这儿再转下,就不会算重了,,,
其实是个很显然的事儿?主要可能还是$gql$太傻逼了嘤嘤嘤
然后因为$gql$语文太差了所以表述能力贼差可能上一段表述得不是很清楚,,,然而我也懒得重写了,,,如果有问题在评论区港就是了$kk$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=30+10,M=5e3+10; int n,m,g[N],f[N][M],sum[N],pre[N][M],as[N]; struct nod{int g,id;}node[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il bool cmp(nod gd,nod gs){return gd.g>gs.g;} il void work(ri n,ri m) { if(!n)return; if(pre[n][m]==n){work(pre[n][m],m-n);rp(i,1,n)++as[node[i].id];return;} work(pre[n][m],m-(n-pre[n][m]));rp(i,pre[n][m]+1,n)as[node[i].id]=1;return; } int main() { //freopen("5105.in","r",stdin);freopen("5105.out","w",stdout); n=read();m=read();rp(i,1,n)node[i]=(nod){read(),i};sort(node+1,node+1+n,cmp);rp(i,1,n)sum[i]=sum[i-1]+node[i].g;memset(f,63,sizeof(f));f[0][0]=0; rp(i,1,n) rp(j,i,m) { f[i][j]=f[i][j-i];pre[i][j]=i; rp(k,0,i-1)if(f[i][j]>f[k][j-(i-k)]+(sum[i]-sum[k])*k)pre[i][j]=k,f[i][j]=f[k][j-(i-k)]+(sum[i]-sum[k])*k; } printf("%d\n",f[n][m]); work(n,m); rp(i,1,n)printf("%d ",as[i]); return 0; }
[X]数字组合
无脑$dp$,,,?
考虑设$f_{i,j}$表示前$i$个数拼出$j$的方案数,无脑背包下就好,,,?
$over$
背包板子我居然打了10$min$,,,是不是小水题做多了会影响智商昂$TT$#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=100+10,M=10000+10; int n,m,a[N],f[M]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } int main() { //freopen("5201.in","r",stdin);freopen("5201.out","w",stdout); n=read();m=read();rp(i,1,n)a[i]=read();f[0]=1; rp(i,1,n) my(j,m,a[i])f[j]+=f[j-a[i]]; printf("%d\n",f[m]); return 0; }
[X]自然数拆分
又是个无脑$dp$,,,
考虑设$f_{i}$表示拼出$i$的方案数,于是有$f_{i}=\sum f_{j}+f_{i-j}$
$over$
完全背包板子昂$QwQ$#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int M=4000+10,mod=2147483648; int n,f[M]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } main() { //freopen("5202.in","r",stdin);freopen("5202.out","w",stdout); n=read();f[0]=1; rp(i,1,n)rp(j,i,n)f[j]=(f[j]+f[j-i])%mod; printf("%lld\n",f[n]-1>=0?f[n]-1:mod-1); return 0; }
[X]$Jury\ Compromise$
做过了,看这儿
[X]$Coins$
做过了,看这儿
[X]石子合并
无脑区间$dp$
设$f_{l,r}$,表示$[l,r]$的最小代价,做完了
几百年前的代码,贼丑,$QAQ$
$upd:$我在$CH$上交了下,发现题目还是有点儿区别,,,最大的区别在这不是个环,,,所以连断环为链都不需要,,,$QAQ$
$over$
View Code#include<bits/stdc++.h> using namespace std; int n,m,a[210],f[222][222],f1[222][222],sum[404],q=0,ww,e,maxl=0,minl=999999999,i,j,l; int main() { cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; a[i+n]=a[i]; } for(i=1;i<=2*n;i++)sum[i]=sum[i-1]+a[i]; for(l=2;l<=n;l++) { for(i=1;i<=2*n-l+1;i++) { j=i+l-1; f[i][j]=999999; f1[i][j]=0; for(int k=i;k<=j-1;k++) { f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]); f1[i][j]=max(f1[i][j],f1[i][k]+f1[k+1][j]+sum[j]-sum[i-1]); } } } for(i=1;i<=n;i++) { maxl=max(maxl,f1[i][i+n-1]); minl=min(minl,f[i][i+n-1]); } cout<<minl<<endl<<maxl; return 0; }
[X]$Polygon$
做过了,看这儿
[X]金字塔
想到了那个点就不难,不然还是有点儿难度的欸$QAQ$
主要就是要想到一个子树对应一个区间?所以考虑设$f_{l,r}$表示$[l,r]$这个区间作为一颗子树的方案数$QwQ$
然后一个比较有趣的点是考虑怎么转移能保证是不重不漏的$QwQ$,就考虑枚举$[l,r]$中第一颗子树的结束点$k$.然后就有$f_{l,r}=\sum f_{l+1,k-1}\cdot f_{k,r-1}$,当然,还可以从$f_{l-1,r+1}$转移来
综上,就是$f_{l,r}=f_{l-1,r+1}+\sum_{col_{l}=col_{k}}f_{l+1,k-1}\cdot f_{k,r}$(当且仅当col_{l}=col_{r}
记得开$ll$鸭
$over$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=300+10,mod=1e9; int n,f[N][N]; char str[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il int solve(ri l,ri r) { if(str[l]!=str[r])return 0;if(l>r)return 0;if(l==r)return 1;if(f[l][r]!=-1)return f[l][r]; f[l][r]=0; rp(i,l+2,r-1)if(str[l]==str[r])f[l][r]=(f[l][r]+1ll*solve(l+1,i-1)*solve(i,r)%mod)%mod; f[l][r]=(f[l][r]+solve(l+1,r-1))%mod; return f[l][r]; } main() { //freopen("5302.in","r",stdin);freopen("5302.out","w",stdout); scanf("%s",str+1);n=strlen(str+1);memset(f,-1,sizeof(f)); printf("%lld\n",solve(1,n)); return 0; }
[X]没有上司的舞会
树形$dp$入门题,,,?
很早以前就听说过这题了但一直没做,,,
直接考虑设$f_{i,0/1}$表示考虑了$i$及它的子树了,$i$这个点去不去的最大快乐值
$over$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=6000+10; int n,h[N],f[N][2],head[N],ed_cnt,fa[N],rt; struct ed{int to,nxt;}edge[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il void ad(ri to,ri fr){edge[++ed_cnt]=(ed){to,head[fr]};head[fr]=ed_cnt;fa[to]=fr;} il void solve(ri x){e(i,x)solve(t(i)),f[x][0]+=max(f[t(i)][0],f[t(i)][1]),f[x][1]+=f[t(i)][0];f[x][1]+=h[x];return;} int main() { //freopen("5401.in","r",stdin);freopen("5401.out","w",stdout); n=read();rp(i,1,n)h[i]=read();rp(i,1,n){ri x=read(),y=read();ad(x,y);} rp(i,1,n)if(!fa[i])rt=i;solve(rt);printf("%d\n",max(f[rt][0],f[rt][1])); return 0; }
[X]选课
无脑树形$dp$入门题,,,?
和上一个差不多,状态一样,只是转移有点儿区别,$over$
$over$
然后弱智$gql$就打了$1.5h$才做完,,,身败名裂了$TT$
就,其实这题和上题还是有点儿区别,,,就根本不用设那个0/1的,,,打了我半天我才发现我题意理解错了,,,你们呆我屎猫
其实是个无脑树形背包,,,$get$错了题意自然而然题目类型也判断的是错的昂$QAQ$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=300+10; int s[N],ed_cnt,head[N],n,m,f[N][N],as; bool vis[N][N][2]; struct ed{int to,nxt;}edge[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il void ad(ri fr,ri to){edge[++ed_cnt]=(ed){to,head[fr]};head[fr]=ed_cnt;} il void solve(ri x){e(i,x){solve(t(i));my(j,m+1,1)rp(k,0,j-1)f[x][j]=max(f[x][j],f[t(i)][k]+f[x][j-k]);}} int main() { freopen("2014.in","r",stdin);freopen("2014.out","w",stdout); n=read();m=read(); rp(i,1,n)ad(read(),i),f[i][1]=read(); solve(0);printf("%d\n",f[0][m+1]); return 0; }
[ ]$Accumulation\ Degree$
写这儿辣
[X]$Naptime$
做过了,看这儿
[X]环路运输
考虑先断环为链并日常长度×2?
然后考虑这道题变成了什么样儿?就,求$max(A_{i}+A_{j}+i-j)$,其中$i\leq 2\cdot n,j\leq 2\cdot n,i-j\leq \frac{n}{2}$
考虑枚举$i$,然后现在就是要求$max(A_{j}-j)$,显然考虑单调队列?
这样儿复杂度均摊下来就差不多是$O(n)$的,$over$
话说这真的是个$dp$,,,?
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=1e6+10; int n,a[N<<1],que[N<<1],head,tail,as; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } struct gdgs { int que[N<<1],head,tail; gdgs(){head=1,tail=0;} il int top(){return a[que[head]]-que[head];} il void push(ri x){while(a[que[tail]]-que[tail]<=a[x]-x && tail>=head)--tail;que[++tail]=x;} il void clr(ri x){while(que[head]<x && tail>=head)++head;} }qwq; int main() { //freopen("5501.in","r",stdin);freopen("5501.out","w",stdout); n=read();rp(i,1,n)a[i]=a[i+n]=read(); rp(i,1,n<<1) { qwq.clr(i-n/2); if(i>=n)as=max(as,a[i]+i+qwq.top());qwq.push(i); } printf("%d\n",as); return 0; }
[X]$Broken\ Robot$
做过了,看这儿
[X]$Mondriaan's\ Dream$
做过了,看这儿
[X]炮兵阵地
做过了,看这儿
[X]开车旅行
很久以前就想做了,,,然后一直没做嘤嘤嘤
考虑预处理出从每个城市$i$出发,小$A$和小$B$分别会去的第一个城市,记为$nxta_{i}$和$nxtb_{i}$
然后考虑再设个$f_{i,j,0/1}$表示从$i$出发,经过$2^{j}$个城市,从小A/小B开始最终到的城市,$l_{a/b,i,j,0/1}$表示路程
显然瞎倍增转移下就好,,,
然后后面也瞎倍增下就做完辣,,
$over$
昂然后首先第一个难点就在预处理,,,这儿有三个方法,一个是用$set$,一个是用双向链表,还一个是用$splay$.因为挺久没练$splay$了,所以估计我之后放的$code$会是$set$版本的,,,?但这两种方法还是都会港下的$QwQ$
首先港下$set$的趴$QwQ$,考虑从后往前加入$set$,顺便把每个点的后边的最近和次近的点就能直接找到了,$over$
双向链表的思路比较类似,但感觉复杂度也许好看些,,,?感觉而已$QwQ$大致思路是先排序,然后考虑从前往后找,显然对第一个点来说所有点都在它后边,于是就能很轻松地找到第一个点的$nxt$,然后就把第一个点删了,这样第二个点就变成第一个点了,这么做下去就好鸭$QwQ$
$splay$其实也差不多鸭$QwQ$和$set$一样儿的思想,然后直接查询$pre$和$nxt$就好$QwQ$
$umm$倍增还是详细点儿港趴,,,
首先还是解释下那几个预处理的数组的意思_(:з」∠)_
其实$f$是比较好解释的$QwQ$?$f_{i,j,0}$指小$a$走第一步,以$i$为起点,走$2^{j}$到达的城市.$f_{i,j,1}$指小$b$走第一步
然后这个$l$我大概港下$QwQ$,其实也还是挺好解释的来着$QwQ$.$l_{a,i,j,0}$指小$a$走第一步,以$i$为起点,走$2^{j}$,小$a$走的路程.$l_{a,i,j,1}$指小$a$走第一步,小$b$走的路程.$l_{b,i,j,0}$指小$b$走第一步,小$a$走的路程,$l_{b,i,j,1}$指小$b$走第一步,小$b$走的路程
变量有点儿多但思路还是挺顺的嘛$QwQ$
然后瞎转移就成$QwQ$,另外,记得特判边界昂$QwQ$
还有一个小细节,是在转移的时候,不难发现,因为$2^{i}$为偶数,所以从谁出发的走了$2^{i}$之后依然是从谁出发.但这儿有个细节,就当$i=1$的时候,因为它实际上是拆成$2^{i-1}$和$2^{i-1}$,就会导致出现奇数,也就是说变为从谁出发转移中就变为另一个人出发,所以对$i=1$要提前处理掉,不能一块儿做昂$QwQ$
真·over?
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define lf double #define int long long #define gc getchar() #define mp make_pair #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) const int N=100000+10,inf=1e9+10;const lf eps=1e-9; int n,h[N],f[N][20][2],la[N][20][2],lb[N][20][2],as1,as2,as; lf tmp_as; il int read() { ri x=0;rb y=1;rc ch=gc; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } namespace gdgs { int rt,nod_cnt; struct node{int fa,ch[2],val,cnt,sz,nam;il void pre(ri x,ri fat,ri name){ch[0]=ch[1]=0;fa=fat;val=x;cnt=sz=1;nam=name;}}tr[N]; struct qwq{int nam,hei;}qaq[5]; il int abs(ri x){return x>0?x:-x;} il bool cmp(qwq gd,qwq gs){return abs(gd.hei)==abs(gs.hei)?gd.hei<gs.hei:abs(gd.hei)<abs(gs.hei);} il void pushup(ri x){tr[x].sz=tr[tr[x].ch[0]].sz+tr[tr[x].ch[1]].sz+tr[x].cnt;} il void rotate(ri x) { ri fa=tr[x].fa,grdfa=tr[fa].fa;bool op1=tr[fa].ch[1]==x,op2=tr[grdfa].ch[1]==fa; tr[grdfa].ch[op2]=x;tr[x].fa=grdfa; tr[fa].ch[op1]=tr[x].ch[op1^1];tr[tr[x].ch[op1^1]].fa=fa; tr[fa].fa=x;tr[x].ch[op1^1]=fa; pushup(fa);pushup(x); } il void splay(ri x,ri goal) { while(tr[x].fa!=goal) { ri fa=tr[x].fa,grdfa=tr[fa].fa; if(grdfa!=goal)(tr[fa].ch[0]==x)^(tr[grdfa].ch[0]==fa)?rotate(x):rotate(fa); rotate(x); } if(!goal)rt=x; } il void insert(ri x,ri nam) { ri nw=rt,fa=0; while(nw && tr[nw].val!=x)fa=nw,nw=tr[nw].ch[x>tr[nw].val]; nw=++nod_cnt;if(fa)tr[fa].ch[x>tr[fa].val]=nod_cnt;tr[nod_cnt].pre(x,fa,nam); splay(nw,0); } il void fd(ri x){ri nw=rt;if(!nw)return;while(tr[nw].ch[x>tr[nw].val] && x!=tr[nw].val)nw=tr[nw].ch[x>tr[nw].val];splay(nw,0);} il int ask_pr(ri x){fd(x);ri nw=tr[rt].ch[0];while(tr[nw].ch[1])nw=tr[nw].ch[1];return nw;} il int ask_nxt(ri x){fd(x);ri nw=tr[rt].ch[1];while(tr[nw].ch[0])nw=tr[nw].ch[0];return nw;} il void pre_nxt() { insert(inf,0);insert(inf+1,0);insert(-inf,0);insert(-inf-1,0);f[n-1][0][1]=n;lb[n-1][0][1]=abs(h[n]-h[n-1]);insert(h[n],n);insert(h[n-1],n-1); my(i,n-2,1) { insert(h[i],i); qaq[1].nam=tr[ask_pr(h[i])].nam,qaq[1].hei=h[qaq[1].nam]-h[i]; qaq[2].nam=tr[ask_pr(h[qaq[1].nam])].nam;qaq[2].hei=h[qaq[2].nam]-h[i]; qaq[3].nam=tr[ask_nxt(h[i])].nam,qaq[3].hei=h[qaq[3].nam]-h[i]; qaq[4].nam=tr[ask_nxt(h[qaq[3].nam])].nam;qaq[4].hei=h[qaq[4].nam]-h[i]; sort(qaq+1,qaq+1+4,cmp); f[i][0][1]=qaq[1].nam;f[i][0][0]=qaq[2].nam;lb[i][0][1]=abs(qaq[1].hei);la[i][0][0]=abs(qaq[2].hei); } } } il void pre() { rp(i,1,n) { f[i][1][0]=f[f[i][0][0]][0][1];f[i][1][1]=f[f[i][0][1]][0][0]; if(f[i][1][0])la[i][1][0]=la[i][0][0],la[i][1][1]=lb[f[i][0][0]][0][1]; if(f[i][1][1])lb[i][1][1]=lb[i][0][1],lb[i][1][0]=la[f[i][0][1]][0][0]; } for(ri j=2;((1<<j)|1)<=n;++j) rp(i,1,n-(1<<j)) { f[i][j][0]=f[f[i][j-1][0]][j-1][0];f[i][j][1]=f[f[i][j-1][1]][j-1][1]; if(f[i][j][0])la[i][j][0]=la[i][j-1][0]+la[f[i][j-1][0]][j-1][0],la[i][j][1]=la[i][j-1][1]+la[f[i][j-1][0]][j-1][1]; if(f[i][j][1])lb[i][j][0]=lb[i][j-1][0]+lb[f[i][j-1][1]][j-1][0],lb[i][j][1]=lb[i][j-1][1]+lb[f[i][j-1][1]][j-1][1]; } } il void query(ri x,ri dis,ri &as1,ri &as2,rb y) { //printf("x=%d dis=%d as1=%d as2=%d y=%d\n",x,dis,as1,as2,y); if(!y) { my(i,19,0) if(f[x][i][0] && la[x][i][0]+la[x][i][1]<=dis) {dis-=la[x][i][0]+la[x][i][1];as1+=la[x][i][0];as2+=la[x][i][1];/*printf(" i=%d\n",i);*/query(f[x][i][0],dis,as1,as2,y^(i==0));return;} } else { my(i,19,0) if(f[x][i][1] && lb[x][i][0]+lb[x][i][1]<=dis) {dis-=lb[x][i][0]+lb[x][i][1];as1+=lb[x][i][0];as2+=lb[x][i][1];/*printf(" i=%d\n",i);*/query(f[x][i][1],dis,as1,as2,y^(i==0));return;} } } main() { //freopen("1081.in","r",stdin);freopen("1081.out","w",stdout); n=read();rp(i,1,n)h[i]=read();h[0]=inf;gdgs::pre_nxt();pre(); //rp(j,0,3)rp(i,1,n)printf("(%d,%d) a:f=%d la=%d lb=%d b:f=%d la=%d lb=%d\n",i,j,f[i][j][0],la[i][j][0],la[i][j][1],f[i][j][1],lb[i][j][0],lb[i][j][1]); /*预处理麻油问题!yep!*/ ri x=read();tmp_as=inf; rp(i,1,n) { ri as1=0,as2=0;lf tmp;query(i,x,as1,as2,0); //printf("i=%d as1=%d as2=%d\n",i,as1,as2); if(!as2)continue; tmp=(lf)as1/as2; if(tmp_as>tmp)tmp_as=tmp,as=i; else if(abs(tmp_as-tmp)<=eps && h[i]>h[as])as=i; } printf("%lld\n",as); ri m=read(); while(m--){ri s=read(),x=read(),as1=0,as2=0;query(s,x,as1,as2,0);printf("%lld %lld\n",as1,as2);} return 0; }
[X]$Count\ The\ Repetitions$
感觉这题长得很像做过的样子,,,但找了半天就是没找到是为什么嘤嘤嘤
$umm$有人不能发现$conn(conn(s_2,n_2 ),m)$就是$conn(s_{2},n_2\cdot m)$嘛,,,?
所以可以考虑先求出一个$ {m}' $表示$ conn ( s_{2} , {m}' ) $不能用$ conn(s_{1} , n_{1}) $生成,然后直接就能求出$m$辣$QwQ$
欧克现在就考虑怎么求这个${m}'$,因为打起来挺麻烦我后面就都用$m$表示辣,,,也就说后面所有$m$表示的都${m}'$昂$QwQ$
然后因为后文中的$n_{2}$也就完全麻油意义辣,所以后文所有$n_{1}$都写成$n$,也就说$后面所有n$表示的都$n_{1}$鸭$QwQ$
然后现在发现$m$可能很大,上界是$\frac{|s_{1}|\cdot n_{1}}{|s_{2}|}$,于是考虑先二进制拆分掉,就,假如$m=2^{p_{1}}+2^{p_{2}}+2^{p_{3}}+...$,就可以当做$conn(s_{2},m)$是由$conn(s_{2},2^{p_{1}}),conn(s_{2},2^{p_{2}}),...$拼起来这样儿的
然后还有一个是$n$也挺大的吼,这里可以先假设$n$足够大,即$s_{1}$重复了无数次
然后考虑设$f_{i,j}$表示从$s_{1}[i]$开始,能生成$conn(s_{2},2^{j})$的最少字符数
显然转移有$f_{i,j}=f_{i,j-1}+f_{(i+f_{i,j-1})\ mod\ |s_{1}|,j-1}$
十分显然懒得解释了,,,
然后瞎预处理一通就欧克$QwQ$
然后最后求答案同样瞎搞一通($bushi$就做完辣,,,
$over$
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define lf double #define gc getchar() #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) const int N=1000+10; int n,f[N][35],tot_len,len1,len2,m; char s1[N],s2[N]; il int read() { ri x=0;rb y=1;rc ch=gc; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il bool pre() { rp(i,0,len1-1) {ri pos=i;rp(j,0,len2-1){ri cnt=0;while(s1[pos]!=s2[j]){++pos;pos%=len1;++cnt;if(cnt>len1)return printf("0\n"),0;}++pos;pos%=len1;f[i][0]+=cnt+1;}} rp(j,1,27)rp(i,0,len1-1)f[i][j]=f[i][j-1]+f[(i+f[i][j-1])%len1][j-1]; return 1; } main() { while(~scanf("%s",s2)) { memset(f,0,sizeof(f)); ri n2=read();scanf("%s",s1);n=read();len1=strlen(s1);len2=strlen(s2);tot_len=len1*n;m=0; if(!pre())continue;ri pos=0;my(i,27,0)if(f[pos][i]<=tot_len){/*printf("tot_len=%d f[%d][%d]=%d\n",tot_len,pos,i,f[pos][i]);*/tot_len-=f[pos][i],m+=1<<i,pos+=f[pos][i],pos%=len1;} printf("%lld\n",m/n2); } return 0; }
[ ]$Cleaning\ Shifts$
无脑$dp$,只是要数据结构优化下
话说我还没做过数据结构优化$dp$的题目,,,只听说过,,,所以还挺新奇的嘿$QwQ$
首先显然考虑无脑$dp$怎么搞?
就$f_{i}$表示搞到$i$了的最小代价
转移就$f_{r_{i}}=(f_{x})_{min}+c_{i}$,其中$x\in [l_{i}-1,r_{i]}$
区间最值这种不显然线段树维护就好,,,?
$over$
哦然后一个$attention$,就,这题还挺友好的,坐标范围很小,就直接做就好,否则是要离散化的昂$QwQ
口胡完感$jio$很$easy$的亚子,咕了,$QwQ$
[X]$The\ Battle\ of\ Chibi$
先不考虑数据范围,思考怎么做
设$f_{i,j}$表示以$i$结尾长度为$j$的最长上升子序列个数
转移显然就$f_{i,j}=\sum f_{k,j-1},a_{k}<a_{i}$
然后考虑转移顺序?就$j$在外层$i$在内层.
然后现在的问题在于,数据范围比较大,如果枚举$k$显然会超时$kk$
所以现在就是要优化这个计算$k$的过程
考虑因为$j$在外层,可以先当作$j$是定值,就有$f_{i}=\sum f_{k},a_{k}<a_{i}$
不难想到树状数组?
于是就树状数组优化下就做完了$QwQ$
还有个就,$a_{i}$的范围挺大的,记得离散化昂
View Code#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define lf double #define gc getchar() #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) #define lowbit(x) (x&(-x)) #define lb(x) lower_bound(st+1,st+1+st_cnt,x)-st const int N=1000+10,mod=1e9+7; int n,m,a[N],f[N][N],st[N],st_cnt,cnt,tr[N]; il int read() { ri x=0;rb y=1;rc ch=gc; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il void ad(ri x,ri dat){while(x<=st_cnt)tr[x]=(tr[x]+dat)%mod,x+=lowbit(x);} il int query(ri x){ri ret=0;while(x){ret=(ret+tr[x])%mod;x-=lowbit(x);}return ret;} main() { ri T=read(); while(T--) { printf("Case #%lld: ",++cnt);memset(f,0,sizeof(f)); n=read();m=read();rp(i,1,n)a[i]=st[i]=read();sort(st+1,st+1+n);st_cnt=unique(st+1,st+1+n)-st-1;rp(i,1,n)a[i]=lb(a[i]),f[i][1]=1; rp(j,2,m){memset(tr,0,sizeof(tr));rp(i,1,n)f[i][j]=query(a[i]-1),ad(a[i],f[i][j-1]);} ri as=0;rp(i,1,n)as=(as+f[i][m])%mod;printf("%lld\n",as); } return 0; }
[X]$Fence$
做过了,看这儿
[ ]$cut\ the\ sequence$
咕了,下午写$QAQ$
[ ]任务安排
写这儿辣
[ ]任务安排2
写这儿辣
[ ]任务安排3
太菜了不会斜率优化,咕了
[X]$cats\ trandsport$
写这儿辣
[ ]诗人小$G$
神奇四边形不等式在哪里?
不会,咕了
欢迎催更$QwQ$
反正我也不会写的($bushi$
[ ]再探石子合并
$umm$就数据范围++
于是用个四边形不等式就好
然而我不会
所以会详细写的$QwQ$
[ ]$Gerald\ and\ Giant\ Chess$
本来是可以无脑$dp$的,,,
但是数据范围太大辣$kk$,考虑转化这道题
不难发现,如果没有黑色格子,从左上到右下的方案一个组合数就出来辣$QwQ$
然后就只要求出从左上到右下至少经过一个黑色棋子的方案了$QwQ$
考虑设$f_{i}$表示从左上角走到第$i$个黑色棋子的方案数,用组合数+容斥瞎转移下就好,,,
$over$
[ ]$Connected\ Graph$
写这儿辣
[ ]$hwo\ many\ of\ them?$
挺神的我$jio$得,,,没看书上题解我真没想到$kk$
考虑设$f_{i,j}$表示$i$个点构成的包含$j$条割边的无向连通图数量
然后计数类$dp$呢,有个基本思想,是这样儿的,下课了咕了下午写$QAQ$
[X]$A\ Decorative\ Fence$
写这儿辣
[X]乌龟棋
无脑$dp$
考虑设$f_{i,j,k,p,q}$表示每张牌剩余的数量
$over$
很久以前的$code$了,贼丑$QAQ$
View Code#include<bits/stdc++.h> using namespace std; int n,m,s[400],c[5],dp[41][41][41][41]; bool o; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)cin>>s[i]; for(int i=1;i<=m;i++) { int t; cin>>t; c[t]++; } dp[0][0][0][0]=s[1]; for(int i=0;i<=c[1];i++) for(int j=0;j<=c[2];j++) for(int k=0;k<=c[3];k++) for(int p=0;p<=c[4];p++) { if(i>0)dp[i][j][k][p]=max(dp[i-1][j][k][p]+s[i+j*2+k*3+p*4+1],dp[i][j][k][p]); if(j>0)dp[i][j][k][p]=max(dp[i][j-1][k][p]+s[i+j*2+k*3+p*4+1],dp[i][j][k][p]); if(k>0)dp[i][j][k][p]=max(dp[i][j][k-1][p]+s[i+j*2+k*3+p*4+1],dp[i][j][k][p]); if(p>0)dp[i][j][k][p]=max(dp[i][j][k][p-1]+s[i+j*2+k*3+p*4+1],dp[i][j][k][p]); // cout<<"i="<<i<<" j="<<j<<" k="<<k<<" p="<<p<<" dp="<<dp[i][j][k][p]<<endl; } cout<<dp[c[1]][c[2]][c[3]][c[4]]; return 0; }
[X]花店橱窗
无脑$dp$
甚至连题解都不想写
直接看$code$趴,,,
View Code#include<bits/stdc++.h> using namespace std; long long a[1005],n,i,j,k,ans[1005][1005],maxans; int main() { cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; a[i+n]=a[i]; } for(i=2;i<2*n;i++) for(j=i-1;j>=1 && i-j<n;j--) { for(k=j;k<i;k++) ans[j][i]=max(ans[j][i],ans[j][k]+ans[k+1][i]+a[i+1]*a[k+1]*a[j]); maxans=max(maxans,ans[j][i]); } cout<<maxans; return 0; }
[ ]$Buy\ Low\ Buy\ Lower$
[ ]$Trip$
[ ]$Substract$
[ ]陨石的秘密
[ ]划分大理石
[ ]$Folding$
[X]能量项链
无脑区间$dp$,瞎搞下就好,,,?
懒得写了入门题没什么可写的昂$QAQ$
很久以前的代码,丑,没了
View Code#include<bits/stdc++.h> using namespace std; long long a[1005],n,i,j,k,ans[1005][1005],maxans; int main() { cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; a[i+n]=a[i]; } for(i=2;i<2*n;i++) for(j=i-1;j>=1 && i-j<n;j--) { for(k=j;k<i;k++) ans[j][i]=max(ans[j][i],ans[j][k]+ans[k+1][i]+a[i+1]*a[k+1]*a[j]); maxans=max(maxans,ans[j][i]); } cout<<maxans; return 0; }
[ ]棋盘分割
[X]$Blocks$
叶佬在$NOIp$的时候讲过,所以那时候就落实了$QwQ$
显然区间$dp$?就设$f_{l,r,k}$,表示的$[l,r]$这个颜色区间,然后右侧还有$k$个和$col_{j}$颜色相同的格子的最大贡献(为什么还会有这个$k$呢,挺显然的还$QwQ$,就因为可能有一段中间被消了之后就会出现拖家带口($bushi$)这种情况辣$QwQ$
好像解释得不太清,,,不管了懒得解释了$QAQ$,如果有没$get$的在下面留言下啥的我再重新港下,,,$QAQ$
View Code#include<algorithm> #include<iomanip> #include<cstring> #include<iostream> #include<cstdio> #include<string> using namespace std; #define il inline #define gc getchar() #define ri register int #define rb register bool #define rc register char #define rp(i,l,r) for(ri i=l;i<=r;++i) #define my(i,l,r) for(ri i=l;i>=r;--i) const int N=210; int n,color[N],cnt[N],f[N][N][N],now,ct,ans; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } int bfs(int l,int r,int k) { if(f[l][r][k]!=0)return f[l][r][k];if(l>r)return 0; f[l][r][k]=bfs(l,r-1,0)+(cnt[r]+k)*(cnt[r]+k); rp(i,l,r-1)if(color[i]==color[r])f[l][r][k]=max(bfs(l,i,cnt[r]+k)+bfs(i+1,r-1,0),f[l][r][k]); return f[l][r][k]; } int main() { // freopen("QAQ.in","r",stdin);freopen("QAQ.out","w",stdout); ri T=read(); rp(i,1,T) { memset(color,0,sizeof(color));memset(f,0,sizeof(f));now=1;n=read(); rp(j,1,n){ct=read();if(ct==color[now])++cnt[now];else{++now;cnt[now]=1;color[now]=ct;}} ans=bfs(1,now,0); cout<<"Case "<<i<<": "<<ans<<endl; } return 0; }