“毒瘤出题组” 批斗 大会
1.批斗现场
“毒瘤者下毒瘤题,爆零得分你和我”
“你喜欢 ****** 和出毒瘤题”
2.题目简述
给出两段序列A,B求出两段序列的
(1)LCS长度
(2)LCS个数
(3)在A中尽量靠后的LCS
(4)在A中尽量靠前的LCS
3.题目背景
讲真,出原创题是真心脑袋疼…
有一天,我看了LCS,然后突发奇想…
“能不能求有多少个LCS呢”
然后我模拟了一下…
貌似有方法…
我把用lower_bound查找的那个数组用一个cnt数组分别加起来,不就是乘法原理嘛
“嗯,就这样…”
“某不知名的程姓男子,你要出题不?”
4.心路历程
“这道题貌似有点简单,不能这么水呀…”
“要想一个办法”
“要不我学一学SCOI2019 D2T3?尽量往数学方面靠?”
然后就是一顿难受的出题和造数据过程
最原来的CODE(WRONG):
#include <bits/stdc++.h>
#define inf 1e8+7
using namespace std;
const int maxn=700005;
template <typename t>void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=x*f;
}
int n,num[maxn],b[maxn],cnt[maxn],g[maxn],fir[maxn],a[maxn],flag[10];
int size=0,ans,m;
void init()
{
freopen("juruo.in","r",stdin);
freopen("juruo.out","w",stdout);
}
void readdata()
{
read(n);int x;
for(int i=1;i<=n;i++)
{
read(a[i]);
num[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
read(x);
if(num[x])b[++size]=num[x];
}
for(int i=1;i<=4;i++)
{
read(flag[i]);
}
}
void work()
{
for(int i=1;i<=size;i++)g[i]=inf;
for(int i=1;i<=size;i++)
{
int k=lower_bound(g+1,g+n+1,b[i])-g;
if(g[k]==inf)
{
fir[k]=b[i];
}
++cnt[k];
g[k]=b[i];
ans=max(ans,k);
}
long long ans2=1;
//////ans1
if(flag[1])
{
printf("Ans(1)=");
printf("%d\n",ans);
}
/////ans2
if(flag[2])
{
printf("Ans(2)=");
for(int i=1;i<=ans;i++)
{
ans2=ans2*cnt[i];
}
printf("%lld\n",ans2);
}
/////ans3_max
if(flag[3])
{
printf("Ans(3)=");
for(int i=1;i<=ans;i++)
{
printf("%d ",a[fir[i]]);
}
printf("\n");
}
/////ans4_min
if(flag[4])
{
printf("Ans(4)=");
for(int i=1;i<=ans;i++)
{
printf("%d ",a[g[i]]);
}
printf("\n");
}
}
int main()
{
// init();
readdata();
work();
return 0;
}
“嗯,我的题出好了”
讲一讲我最开始的想法吧。。。
“程,我貌似Hank掉了你的程序!”
“???你怎么会有我的code???”
经过一番请教过后,发现的确有问题
比如
4
1 2 3 4
1 4 2 3
1 1 1 1
然后,我发现我贪心出了问题,经过一番改动
又有了CODE(WRONG):
#include <bits/stdc++.h>
#define inf 1e8+7
using namespace std;
const int maxn=700005;
template <typename t>void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=x*f;
}
int n,num[maxn],b[maxn],cnt[maxn],g[maxn],a[maxn],flag[10];
int size=0,ans,m,tot;
vector<int>ve[105];
int fir[105];
void init()
{
freopen("juruo10.in","r",stdin);
freopen("juruo10.out","w",stdout);
}
void readdata()
{
read(n);int x;
for(int i=1;i<=n;i++)
{
read(a[i]);
num[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
read(x);
if(num[x])b[++size]=num[x];
}
for(int i=1;i<=4;i++)
{
read(flag[i]);
}
}
void work()
{
for(int i=1;i<=size;i++)g[i]=inf;
if(n>100)
{
for(int i=1;i<=size;i++)
{
int k=lower_bound(g+1,g+n+1,b[i])-g;
g[k]=b[i];
ans=max(ans,k);
}
}
else if(n<=100)
{
for(int i=1;i<=size;i++)
{
int k=lower_bound(g+1,g+n+1,b[i])-g;
if(g[k]==inf)
{
tot++;
}
g[k]=b[i];
++cnt[k];
ve[k].push_back(g[k]);
ans=max(ans,k);
}
}
int ans2=1;
//////ans1
if(flag[1])
{
printf("Ans(1)=");
printf("%d\n",ans);
}
/////ans2
if(flag[2])
{
int ans2=1;
printf("Ans(2)=");
for(int i=1;i<tot;i++)
{
int j=0,k=0,len=ve[i].size();
while(ve[i][j]>ve[i+1][0])
{
cnt[i]--;
if(j==len-1)break;
j++;
}
fir[i]=j;
}
for(int i=1;i<=tot;i++)
{
ans2=ans2*cnt[i];
}
printf("%d\n",ans2);
}
/////ans3_max
if(flag[3])
{
printf("Ans(3)=");
for(int i=1;i<=tot;i++)
{
int m=ve[i].size();
printf("%d ",a[ve[i][fir[i]]]);
}
printf("\n");
}
/////ans4_min
if(flag[4])
{
printf("Ans(4)=");
for(int i=1;i<=ans;i++)
{
printf("%d ",a[g[i]]);
}
printf("\n");
}
}
int main()
{
//init();
readdata();
work();
return 0;
}
改动的地方:
“程,你的code有问题呀!”
“WHAT?怎么你也有我的CODE?”
比如这组数据
4
1 2 3 4
1 4 3 2
1 1 1 1
错误之处:
改动的地方:
临时花了10分钟改代码…
于是有了CODE 第三版(欢迎Hank):
#include <bits/stdc++.h>
#define inf 1e8+7
using namespace std;
const int maxn=700005;
template <typename t>void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=x*f;
}
int n,num[maxn],b[maxn],cnt[maxn],g[maxn],a[maxn],flag[10],id[maxn];
int size=0,ans,m,tot;
vector<pair<int,int> >ve[105];
int fir[105];
void init()
{
freopen("juruo.in","r",stdin);
// freopen("juruo.out","w",stdout);
}
void readdata()
{
read(n);int x;
for(int i=1;i<=n;i++)
{
read(a[i]);
num[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
read(x);
if(num[x])
{
b[++size]=num[x];
id[b[size]]=i;
}
}
for(int i=1;i<=4;i++)
{
read(flag[i]);
}
}
void work()
{
for(int i=1;i<=size;i++)g[i]=inf;
if(n>100)
{
for(int i=1;i<=size;i++)
{
int k=lower_bound(g+1,g+n+1,b[i])-g;
g[k]=b[i];
ans=max(ans,k);
}
}
else if(n<=100)
{
for(int i=1;i<=size;i++)
{
int k=lower_bound(g+1,g+n+1,b[i])-g;
if(g[k]==inf)
{
tot++;
}
g[k]=b[i];
++cnt[k];
ve[k].push_back(make_pair(id[g[k]],g[k]));
ans=max(ans,k);
}
}
int ans2=1;
//////ans1
if(flag[1])
{
printf("Ans(1)=");
printf("%d\n",ans);
}
/////ans2
if(flag[2])
{
int ans2=1;
printf("Ans(2)=");
for(int i=1;i<tot;i++)
{
int j=0,k=0,len=ve[i].size();
int xx=ve[i][j].first;
int yy=ve[i+1][0].first;
int xxs=ve[i][j].second;
int yys=ve[i+1][0].second;
while(ve[i][j].second>ve[i+1][0].second)
{
cnt[i]--;
if(j==len-1)break;
j++;
}
for(int k=0;k<len;k++)
{
if(ve[i][k].first>ve[i+1][0].first)
{
cnt[i]--;
if(j==len-1)break;
j++;
}
}
fir[i]=j;
}
for(int i=1;i<=tot;i++)
{
ans2=ans2*cnt[i];
}
printf("%d\n",ans2);
}
/////ans3_max
if(flag[3])
{
printf("Ans(3)=");
for(int i=1;i<=tot;i++)
{
int m=ve[i].size();
printf("%d ",a[ve[i][fir[i]].second]);
}
printf("\n");
}
/////ans4_min
if(flag[4])
{
printf("Ans(4)=");
for(int i=1;i<=ans;i++)
{
printf("%d ",a[g[i]]);
}
printf("\n");
}
}
int main()
{
init();
readdata();
work();
return 0;
}