Codeforces Round #634 (Div. 3)(E() F 思维+递增)

题目链接

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();
}
发布了536 篇原创文章 · 获赞 71 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/105566330
今日推荐