得分:100+0+0
本次考试相较于昨天的三道题;
T1 没有什么变化,稍加分析就可以看出是差分,但是根据这么久的做题,对于差分主要是有两点需要注意(树上差分单独):
1、差分的边界一定要注意,到底有没有0,最后是n+1还是n(今天一位因为没有从0开始差分,被wuvin卡成0分);
2、注意加的区间,是两边都闭还是左闭右开,一定要注意。
T2 难度有所增加,这道题教会了我,考试的时候在无法保证自己的“正解”的正确性时,一定要分段打代码,今天考试时我发现挂个链表,每次把单调递减的序列减一减,试了几个数据都对了,以为自己很稳,就直接交了,结果炸成0分(蒟蒻。。),所以一定要分段打,保证拿分;
T3 区间DP直接弃疗,区间DP状态的选择在简单题比较明显,至于真正的难度(我也没作过几道区间DP,所以无法评价);DP题主要就是方程的考虑要全面,可以手玩一些小数据,找找不同的情况。
T2:
题意:给你一个序列,每次将序列中连续严格下降的子序列减去,直至最后只剩单调递增的序列,输出这个序列。
题解:可以定义三个队列q1,q2,q3,然后每次将要减去的数丢进q1,将暂时不丢的扔进q2,q3中临时存储丢掉的数用来更新答案(其实q3并没有用,可以在丢的时候就更新答案)
#include
using namespace std;
const int N = 100005;
int T,n,a[N],l[N],r[N];
bool b[N];
inline int Readint(){
int i=0,f=1;char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0';
return i*f;
}
inline void solve(){
n=Readint();
for(int i=1;i<=n;++i){
a[i]=Readint();
l[i]=i-1;r[i]=i+1;
}
r[0]=1;
a[n+1]=0x3fffffff;
queue<int>q,q2,q3;
for(int i=1;i<=n;++i){
if((a[l[i]]>a[i]||a[i]>a[r[i]])){
q.push(i);
}
}
while(!q.empty()){
while(!q.empty()){
int u=q.front();
q.pop();
q3.push(u);
if(a[l[u]]<=a[u]&&l[u]>=0)q2.push(l[u]);
if(a[u]<=a[r[u]]&&r[u]<=n)q2.push(r[u]);
}
while(!q3.empty()){
int u=q3.front();
b[u]=1;
q3.pop();
l[r[u]]=l[u];
r[l[u]]=r[u];
}
while(!q2.empty()){
int u=q2.front();
q2.pop();
if(!b[u]&&(a[l[u]]>a[u]||a[u]>a[r[u]])){
q.push(u);
}
}
}
int ans=0;
for(int i=1;i<=n;++i){
if(!b[i]){
++ans;
}
}
cout<for(int i=1;i<=n;++i){
if(!b[i]){
cout<" ";
}
}
cout<inline void clear(){
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
memset(r,0,sizeof(r));
memset(l,0,sizeof(l));
}
int main(){
// freopen("sort.in","r",stdin);
T=Readint();
while(T--){
solve();
clear();
}
return 0;
}
T3:
题意:给你一个01串,当三个及以上的相同字符连在一起时就会抵消掉,保证一开始没有三个相同的字符连在一起,现在要求你插入一些0和1,将整个字符串抵消完,求最小代价。
T<=10,n<=200;
读完题发现这是一道区间DP题,我们可以定义 dp[ i ][ j ]表示将区间[i,j]抵消完的最小代价 ,我们把相邻的且相同的和在一起,用num[i]表示它的点权;转移有四种:
3-num[i] i==j
dp[i][k] + dp[k+1][j] i<=k < j
dp[i+1][k-1]+dp[k+1][j] color[i]==color[j]==color[k] & num[i]+num[j]<4 & num[k]==1
dp[l+1][j-1] +max(0,3-num[i]-num[j])
一个小样例:1100110010110100110011
答案为3不是2
#include
using namespace std;
const int N = 205;
int T,len,cnt,ch[N],num[N],dp[N][N];
char s[N];
inline int Readint(){
int i=0,f=1;char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0';
return i*f;
}
inline void solve(){
memset(dp,0x3f,sizeof(dp));
memset(num,0,sizeof(num));
scanf("%s",s+1);
len=strlen(s+1);cnt=0;
for(int i=1;i<=len;i++){
if(s[i]!=s[i-1]) ch[++cnt]=s[i],num[cnt]=1;
else num[cnt]++;
}
for(int i=cnt;i>=1;i--)
for(int j=i;j<=cnt;j++){
if(i==j){dp[i][j]=3-num[i];continue;}
if(ch[i]==ch[j]){
dp[i][j]=dp[i+1][j-1]+max(0,3-num[i]-num[j]);
if(num[i]+num[j]<4)
for(int k=i+2;k2)
if(num[k]==1)
dp[i][j]=min(dp[i][j],
dp[i+1][k-1]+dp[k+1][j-1]);
}
for(int k=i;k1][j]);
}
cout<1][cnt]<int main(){
// freopen("beans.in","r",stdin);
T=Readint();
while(T--){
solve();
}
return 0;
}