2019.7.31
Merging Two Decks
https://cn.vjudge.net/problem/CodeForces-234H
贪心+模拟,
可以把连续的1或0看场一块,这样每一个序列都分成若干块。合并的时候‘按块合并’。
如果两个序列块数不同,那么块数少的总能并入块数多的。
如果块数相同,那么只需枚举开头属于哪一块。
综上,只需要用双指针同时遍历两次即可,第一次假设合并的序列1开头,第二次假设合并的序列0开头
自己的代码太丑,还是标程比较简洁
#include
#include
#include
using namespace std;
int A[200005];
int V[200005];
int N, M;
vector solve(int type)
{
int K = 0, x = 1, y = N + 1;
while (x <= N || y <= N + M)
{
while (x <= N && A[x] == type)
V[K++] = x++;
while (y <= N + M && A[y] == type)
V[K++] = y++;
type = 1 - type;///变换状态
}
/// 在该翻转的时候就翻转,相邻的两个不一样就翻转;在最后的后一步加一个哨兵0;防止……
vector answer;
for (int i = 0; i < N + M; ++i)
if (A[V[i]] != A[V[i + 1]]) ///最后一个多一个哨兵
answer.push_back(i + 1);
return answer;
}
int main() {
//ifstream cin("input.txt");
// ofstream cout("output.txt");
cin >> N;
for (int i = 1; i <= N; ++i)
cin >> A[i];
cin >> M;
for (int i = N + 1; i <= N + M; ++i)
cin >> A[i];
vector answer = solve(0);
if (solve(1).size() <= answer.size())
answer = solve(1);
else answer = solve(0);
///V是最后一次调用slove的结果
for (int i = 0; i < N + M; ++i)
cout << V[i] << " ";
cout << "\n";
cout << answer.size() << "\n";
for (int i = 0; i < int(answer.size()); ++i)
cout << answer[i] << " ";
cout << "\n";
}
The Fair Nut and Strings
https://cn.vjudge.net/problem/CodeForces-1084E思维题,通过trie树来计数。每个字符串刚好对应了一个trie树节点
字符串ab构成二叉树,每次向下走的过程,如果不加限制,那么节点数2,我们先假设没有限制的,2
如果s[i]等于a,那么这个节点可以扩展出a,b两个,
如果s[i]等于b,那么这个节点只能扩展出b,因为字典序必须>=s。
同理,t[i]=a的时候不能扩展出b,因为字典序必须<=t
代码相当简洁:https://blog.csdn.net/black_miracle/article/details/86536972
Can Bash Save the Day
https://cn.vjudge.net/problem/CodeForces-757G动态点分治。过于复杂qwq
日后填坑
Array Splitting
https://cn.vjudge.net/problem/CodeForces-1197C
巧妙的贪心问题
设
依次类推,我们粗略发现一个大区间分裂成小区间时,区间贡献之和减少一个bi
粗略证明:因为一旦某个点成为左端点,那么它不再与比它小的数产生贡献
a1必然是左端点
我们再在[2,n]找到k-1个左端点,就能得到k个区间。
按照bi的定义求出bi,然后sort,取最大的(k-1)个求和,然后减去它
#include<bits/stdc++.h>
/*--------------------------------------------------------------------*/
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define max1 (500+10)
#define max2 (1000+10)
#define maxn (1000000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL cout<<endl
#define fi freopen("input.txt","r",stdin)
#define fo freopen("output.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
/*--------------------------------------------------------------------*/
int n,k,a[maxn],b[maxn];
int main()
{
RD2(n,k);
for(int i=1;i<=n;i++){RD1(a[i]);b[i]=a[i]-a[i-1];} b[1]=0;
sort(b+1,b+1+n);
int sum=0;
for(int i=n,cnt=1;cnt<k;i--,cnt++)sum+=b[i];
printf("%d",a[n]-a[1]-sum);
return 0;
}
中等难度dp题,和整数划分的dp有点像。。
设
num张牌分给person个人得到的最大值,可以从person-1个人的基础上加入1个人,并分配给他delt张牌转移而来
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define max1 (500+10)
#define max2 (1000+10)
#define maxn (100000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL cout<<endl
#define fi freopen("input.txt","r",stdin)
#define fo freopen("output.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int n,k;
int c[maxn],f[maxn],rec[maxn],dv[maxn],h[20];
vector<int>a;
ll dp[5050][505];
int main()
{
RD2(n,k);
for(int i=1;i<=n*k;i++){int t;RD1(t);rec[t]++;}
for(int i=1;i<=n;i++)
{
int t;RD1(t);
if(!dv[t])a.push_back(t);
dv[t]++;
}
for(int i=1;i<=k;i++)RD1(h[i]);
ll ans=0;
while(a.size())
{
//see(a.size());
ll tot=1LL*rec[a.back()],p=1LL*dv[a.back()];a.pop_back();
CLR(dp);
//see(tot),see(p);
for(ll ps=1;ps<=p;ps++)
for(ll i=1;i<=tot;i++)
{//see(ps),see(i),NL;
for(int v=1;v<=k&&v<=i;v++)
dp[i][ps]=max(dp[i][ps],dp[i-v][ps-1]+h[v]);
//see(i),see(ps),see(dp[i][ps]),NL;
}
ans+=dp[tot][p];
}
printf("%lld",ans);
return 0;
} 简单区间dp或者用巧妙的lcs
两种思路,见https://www.cnblogs.com/pkgunboat/p/10361375.html里面讲的十分详细
dp解法比较好想一点
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define max1 (500+10)
#define max2 (1000+10)
#define maxn (5000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL cout<<endl
#define fi freopen("input.txt","r",stdin)
#define fo freopen("output.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int dp[maxn][maxn];
int a[maxn],n;
int main()
{
RD1(n);for(int i=1;i<=n;i++)RD1(a[i]);
int len=1;
for(int i=2;i<=n;i++)if(a[i]!=a[len])
a[++len]=a[i];
n=len;
INF(dp);
for(int l=0;l<=n;l++)
for(int st=1;st+l<=n;st++)
{
int ed=st+l;if(ed==st)dp[st][st]=0;
if(a[st-1]!=a[ed+1])
dp[st][ed+1]=min(dp[st][ed]+1,dp[st][ed+1]),
dp[st-1][ed]=min(dp[st][ed]+1,dp[st-1][ed]);
else
dp[st][ed+1]=min(dp[st][ed]+1,dp[st][ed+1]),
dp[st-1][ed]=min(dp[st][ed]+1,dp[st-1][ed]),
dp[st-1][ed+1]=min(dp[st][ed]+1,dp[st-1][ed+1]);
}
printf("%d",dp[1][n]);
return 0;
}
Mashmokh and ACM
简单dp
用当前状态更新未来状态,要比用过去状态更新当前状态方便一些
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define max1 (500+10)
#define max2 (1000+10)
#define maxn (5000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL cout<<endl
#define fi freopen("input.txt","r",stdin)
#define fo freopen("output.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll dp[2020][2020];
int n,k;
int main()
{
RD2(n,k);
for(int i=1;i<=n;i++)dp[1][i]=1;
for(int pos=1;pos<k;pos++)
for(int v=1;v<=n;v++)
for(int nx=v;nx<=n;nx+=v)
dp[pos+1][nx]=(dp[pos][v]+dp[pos+1][nx])%mod;
ll sum=0;
for(int i=1;i<=n;i++)sum=(sum+dp[k][i])%mod;
printf("%lld",sum);
return 0;
} Lucky Common Subsequence
https://cn.vjudge.net/problem/CodeForces-346B 比较难搞的三维dp,思路参见https://www.cnblogs.com/justPassBy/p/3963200.html
理解之后,按自己的思路状态转移,但WA了,日后填坑
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define max1 (500+10)
#define max2 (1000+10)
#define maxn (5000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (1000000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL cout<<endl
#define fi freopen("input.txt","r",stdin)
#define fo freopen("output.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
char s1[200],s2[200],v[200];
int dp[200][200][200];
int f[200];
int pre[200][200][200][3];
void getf(char *s)
{
int l=strlen(s);
int fail=-1,pos=0;f[0]=-1;
while(pos<l)
{
while(fail!=-1&&s[pos]!=s[fail])fail=f[fail];
f[++pos]=++fail;
}
}
void trans(int x,int y,int z,int xx,int yy,int zz,int val)
{
if(dp[x][y][z]<dp[xx][yy][zz]+val)
dp[x][y][z]=dp[xx][yy][zz]+val,
pre[x][y][z][0]=xx,
pre[x][y][z][1]=yy,
pre[x][y][z][2]=zz;
}
int ans[200];
int main()
{
scanf("%s%s%s",s1,s2,v);getf(v);
int l1=strlen(s1),l2=strlen(s2),lv=strlen(v);
NEG(pre);
//for(int i=0;i<lv;i++)see(i),see(f[i]),NL;
for(int i=0;i<l1;i++)for(int j=0;j<l2;j++)for(int k=0;k<lv;k++)
{
if(!i||!j||!k)if(s1[i]==s2[j]&&s1[i]==v[0])
{
dp[i][j][0]=1;//see(i),see(j),see(k),NL;
//pre[i][j][0][0]=pre[i][j][0][1]=pre[i][j][0][2]=0;
}
trans(i+1,j,k,i,j,k,0),trans(i,j+1,k,i,j,k,0);
if(s1[i+1]==s2[j+1])
{
//see(i),see(j),see(k),NL;
trans(i+1,j+1,k,i,j,k,1);
if(s1[i+1]==v[k+1])
trans(i+1,j+1,k+1,i,j,k,1);
else
{
int p=f[k+1];while(~p&&s1[i+1]==v[p])p=f[p];
if(p==-1)p=0;
if(v[p]==s1[i+1])trans(i+1,j+1,p,i,j,k,1);
}
}
}
int pos,val=-1;
for(int i=0;i<lv-1;i++)
if(val<dp[l1-1][l2-1][i])
val=dp[l1-1][l2-1][i],
pos=i;
if(val<=0){printf("0");return 0;}
int ed=val;
int x=l1-1,y=l2-1;
while(~pre[x][y][pos][0])
{
int xx=pre[x][y][pos][0],
yy=pre[x][y][pos][1],
zz=pre[x][y][pos][2];
if(x-xx==1&&y-yy==1&&s1[x]==s2[y])
ans[val--]=s1[x];
x=xx,y=yy,pos=zz;
}//see(val),see(x),see(y),see(pos);
if(s1[x]==s2[y]&&s1[x]==v[0])ans[val]=s1[x];
for(int i=1;i<=ed;i++)printf("%c",ans[i]);
return 0;
}
快手公司福利 1244人发布