这场失策的地方是 当时C过的人比B多 但是自己还在肝B 使得D差几分钟就能出 D(赛后一遍过)
题意 1代表一种菜 2 代表另一个菜 问你偶数区间一分为二 两边各是一种菜 区间最长为
我们可以找到第一个右边不等于左边的菜进行左右枚举即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 100025;
int arr[MAX_N],arr_[MAX_N];
stack <int > st;
int main()
{
int n,maxx = 0;
scanf("%d",&n);
for(int i = 1;i<=n;++i)
scanf("%d",&arr[i]);
for(int i = 2;i<=n;++i)
{
int tmp;
if(arr[i]!=arr[i-1])
{
tmp = 1;
while(i+tmp<=n&&i-1-tmp>=1&&arr[i+tmp]==arr[i]&&arr[i-1-tmp]==arr[i-1])
{
tmp++;
}
maxx = max(maxx,tmp);
}
}
//dbg(maxx);
printf("%d\n",maxx*2);
return 0;
}
B这题一开始无法上手 后来发现实际上你只要把 满足 (1,1) (1,0) (0,1) (0,0) 在一队里面出现的次数为x y z J,那么他在另一队出现的次数就是 num-x,num_-y,num__-z,num___-J;
我们容易得到下列方程 x+y+z+J = n/2 1.
x+y = num__-z+num - x -> x+y+z + x = num + num__ -> n/2- J + x = num + num__
所以我们只要枚举 x和J即可 并且要满足num_ + num___>=n/2-J-X
进行枚举即可得到答案
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 5025;
int ans[MAX_N];
char str[MAX_N],str_[MAX_N];
vector<int > vt,vt_,vt__,vt___;
int main()
{
int n,num = 0,num_ = 0,num__ = 0,num___ = 0,cnt = 0,x=0,y=0,z=0,J=0;
scanf("%d",&n);
scanf("%s",str+1);
scanf("%s",str_+1);
for(int i = 1;i<=n;++i)
{
if(str[i]=='1'&&str_[i]=='1')
{
vt.push_back(i);
num++;
}
else if(str[i]=='1')
{
vt_.push_back(i);
num_++;
}
else if(str_[i]=='1')
{
vt__.push_back(i);
num__++;
}
else
{
vt___.push_back(i);
num___++;
}
}
//dbg2(num,num_);
//dbg2(num__,num___);
int flag = 0;
int ck = num__ + num;
//dbg(ck);
for(int i = 0;i<=min(n/2,num);i++)
{
for(int k = 0;k<=min(n/2,num___)&&i+k<=n/2;k++)
{
if(n/2-k+i==ck&&num_+num__>=n/2-i-k)
{
x = i;
J = k;
flag = 1;
break;
}
}
}
//dbg2(x,J);
if(!flag)
{
printf("-1\n");
}
else
{
for(int i = 0;i<=min(n/2,num_)&&y+x+J<=n/2;i++)
{
for(int j = 0;j<=min(n/2,num__)&&x+y+J+j<=n/2;j++)
{
if(i+j==n/2-x-J)
{
y = i;
z = j;
break;
}
}
}
for(int i = 0;i<x;++i) ans[++cnt] = vt[i];
for(int i = 0;i<y;++i) ans[++cnt] = vt_[i];
for(int i = 0;i<z;++i) ans[++cnt] = vt__[i];
for(int i = 0;i<J;++i) ans[++cnt] = vt___[i];
for(int i = 1;i<=cnt;++i)
i==cnt?printf("%d\n",ans[i]):printf("%d ",ans[i]);
}
return 0;
}
题意 给你好多条街道 定义十字路口为街道相交的地方 问你对每一个十字路口 能重新分配的最大高度为x 满足每条街道大家的相对高度不变
做法 根据样例容易发现 其实答案就是 那个点再两条街道取的离散化后的差 加上矮的那个高度因为要调高度 所以答案为最大值加上升高的高度 于是就是统计行的最大值 r_mx ,列的最大值 c_mx,离散化后的两个数组 行离散化mp,列离散化mp_
但是发现有问题 就是 3 3
1 2 3
1 2 3
1 2 3
这组数据的问题 所以加了个特判 如果某一行或者某一列他的最大值是1 那么直接就取相对的另一个最大值
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 1025;
int mp[MAX_N][MAX_N],mp_[MAX_N][MAX_N],mp__[MAX_N][MAX_N],r_mx[MAX_N],c_mx[MAX_N],b[MAX_N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
scanf("%d",&mp[i][j]);
}
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
b[j] = mp[i][j];
}
sort(b+1,b+1+m);
int sz = unique(b+1,b+1+m)-b-1;
for(int j = 1;j<=m;++j)
{
mp_[i][j] = lower_bound(b+1,b+1+sz,mp[i][j]) - b;
r_mx[i] = max(r_mx[i],mp_[i][j]);
}
}
for(int i = 1;i<=m;++i)
{
for(int j = 1;j<=n;++j)
{
b[j] = mp[j][i];
}
sort(b+1,b+1+n);
int sz = unique(b+1,b+1+n)-b-1;
for(int j = 1;j<=n;++j)
{
mp__[j][i] = lower_bound(b+1,b+1+sz,mp[j][i]) - b;
c_mx[i] = max(c_mx[i],mp__[j][i]);
}
}
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
int tmp = max(mp_[i][j],mp__[i][j])-min(mp_[i][j],mp__[i][j]);
if(mp_[i][j]<=mp__[i][j])
{
if(r_mx[i]==1) printf("%d",c_mx[j]);
else printf("%d",max(c_mx[j],r_mx[i]+tmp));
}
else
{
if(c_mx[j]==1) printf("%d",r_mx[i]);
else printf("%d",max(r_mx[i],c_mx[j]+tmp));
}
j==m?printf("\n"):printf(" ");
}
}
return 0;
}
题意 给你一开始一个01串 后来一个01串 问你不改变一开始01串的01个数 使得构造一个01串使后来那个串出现次数最多
做法 我们知道kmp里面的next数组的定义 next[n] 就是这个字符串后next[n]个前缀字符等于后缀
所以我们只需要先构造出一个 然后再构造next[n]后面的答案 不断去构造即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 500025;
char str[MAX_N],mo[MAX_N];
int Next[MAX_N],n2;
void GetNext()
{
int i=0,j=-1;
while(i<n2)
{
if(j==-1||mo[i]==mo[j])
{
++i,++j,Next[i]=j;
}
else
j=Next[j];
}
return ;
}
int main()
{
int num = 0,num_ = 0,NUM = 0,NUM_ = 0;
scanf("%s",str);
int len = strlen(str);
for(int i = 0;i<len;++i)
{
if(str[i]=='1') num++;
else num_++;
}
scanf("%s",mo);
n2 = strlen(mo);
for(int i = 0;i<n2;i++)
{
if(mo[i]=='1') NUM++;
else NUM_++;
}
Next[0] = -1;
GetNext();
//dbg(Next[n2]);
if(num>=NUM&&num_>=NUM_)
{
printf("%s",mo);
num-=NUM;
num_ -= NUM_;
while(num&&num_)
{
for(int i = Next[n2];i<n2;i++)
{
if(mo[i]=='1') num--;
else num_--;
printf("%c",mo[i]);
if(!num&&NUM||!num_&&NUM_) break;
}
}
while(num)
{
printf("1");
num--;
}
while(num_)
{
printf("0");
num_--;
}
printf("\n");
}
else
{
printf("%s\n",str);
}
return 0;
}