E2. Three Blocks Palindrome (hard version)
题意:给你n长度的序列 并且每个1<=a[i]<=200 现在要你找出最长的子序列
子序列的格式:x x x y y x x x 左边x的个数等于右边x的个数。
做法:思路应该很简单,维护前缀和后缀每个a[i]的数量 y 出现在哪个位置,预处理后缀,枚举前缀,再枚举中间的 200 内的区间和最大值即可
这题卡空间,小到只能开一个200*n的数组 以及一个map
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+2;
int n,a[N];
int pre[N][201],mx;
void solve()
{
map<int,int>mp[201];
scanf("%d",&n);
rep(i,1,n) scanf("%d",&a[i]);
per(i,n,1)
{
rep(j,1,200) pre[i][j]=pre[i+1][j];
pre[i][a[i]]++;
mp[a[i]][pre[i][a[i]]]=i;
}
rep(i,1,n)
{
rep(j,1,200) pre[i][j]=pre[i-1][j];
pre[i][a[i]]++;
}
int ans=0;
rep(i,1,n)
{
//rep(j,1,200) pre[i][j]=pre[i-1][j];
//pre[i][a[i]]++;
if(mp[a[i]][pre[i][a[i]]]){
int l=i+1,r=mp[a[i]][pre[i][a[i]]]-1;
if(l<=r){
int mx=0;
rep(k,1,200){
mx=max(mx,pre[r][k]-pre[l-1][k]);
}
//printf("l:%d r:%d mx:%d\n",l,r,mx);
ans=max(ans,pre[i][a[i]]*2+mx);
}
}
}
rep(i,1,200) ans=max(ans,pre[n][i]);
printf("%d\n",ans);
rep(i,0,n+1)
rep(j,0,200) pre[i][j]=0;
}
int main()
{
int _;cin>>_;while(_--)
solve();
}
F. Robots on a Grid
看懂不会写,然后百度题解:博客
分析的思维很妙。
具体操作就是二维转一维,然后图上倍增一下,计算每个点的终点是在哪个点。有相同终点保留一个为答案即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e6+10;
int fa[N][24],col[N],n,m,b,white[N],black[N];
char s[N];
void solve()
{
scanf("%d%d",&n,&m);
rep(i,1,n){
scanf("%s",s+1);
rep(j,1,m) col[(i-1)*m+j]=s[j]=='0'?0:1;
}
rep(i,1,n){
scanf("%s",s+1);
rep(j,1,m){
int now=(i-1)*m+j;
//printf("now:%d\n",now);
if(s[j]=='U') fa[now][0]=now-m;
else if(s[j]=='D') fa[now][0]=now+m;
else if(s[j]=='L') fa[now][0]=now-1;
else if(s[j]=='R') fa[now][0]=now+1;
}
}
//printf("fa[1][0]:%d\n",fa[1][0]);
n=n*m;
for(int k=1;k<=21;++k) for(int i=1;i<=n;++i) fa[i][k]=fa[fa[i][k-1]][k-1];
//for(int k=0;k<=21;++k)printf("i:%d fa:%d\n",1,fa[1][k]);
rep(i,1,n){
int ne=i;
//printf("ne:%d\n",ne);
for(int k=21;k>=0;--k){
if((1<<k)&n) {
//printf("k:%d\n",k);
ne=fa[ne][k];
}
}
col[i]?white[ne]=1:black[ne]=1;
//printf("i:%d ne:%d\n",i,ne);
}
int ans=0,num=0;
//rep(i,1,n) printf("i:%d b:%d w:%d\n",i,black[i],white[i]);
rep(i,1,n) if(black[i]) ans++,num++; else if(white[i]) ans++;
rep(i,1,n) {
black[i]=white[i]=col[i]=0;
for(int j=1;j<=21;++j) fa[i][j]=0;
}
printf("%d %d\n",ans,num);
}
int main()
{
int _;cin>>_;while(_--)
solve();
}