zoukankan      html  css  js  c++  java
  • uoj#529. 【美团杯2020】114514

    题目描述


    题解

    必须要发掘出性质才能搞,乱找找不满

    一草稿纸的114514越看越草

    发现5只出现一次,而且14是114的子串

    显然可以想到每次按最近的来匹配,一次找出一个114514

    发现114511451414会挂掉,原因是把第二个5的114给拆掉了

    1的数量最多,所以只考虑总量不考虑单独每个

    对比一下4的两种用法,14必须要在5的后面并且少一个1,114没有限制并且多一个1

    那么14即有限制又更优,所以肯定是能匹配14就匹配

    然后就回到了上面的错误做法

    考虑哪里会挂掉,每个5前面必须要留一个4,所以只需要保证匹配完14后每个5都能匹配一个4即可

    把4当成+1,5当成-1,前缀和就是可以匹配14(选1145不改变前缀和)的数量,用队列即可求得限制,当一个5被选的时候判断是否要弹掉队头

    找数用并查集,时间复杂度O(nα)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define ll long long
    //#define file
    using namespace std;
    
    const int b[6]={0,0,1,2,0,1};
    int fa[3][600002],ans[100001][6],D[600002][2],Q,n,m,i,j,k,l,s1,s2,s3,h,t,H,T,s;
    char st[600001];
    
    int gf(int T,int t)
    {
    	static int d[600002],tot,i;
    	tot=0;
    	while (fa[T][t]!=t) d[++tot]=t,t=fa[T][t];
    	fo(i,1,tot) fa[T][d[i]]=t;
    	
    	return t;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("uoj529.in","r",stdin);
    //	freopen("uoj529.out","w",stdout);
    	#endif
    	
    	scanf("%d",&Q);
    	for (;Q;--Q)
    	{
    		scanf("%s",st+1);n=strlen(st+1);m=n/6;
    		h=1;t=0;
    		
    		fa[0][0]=fa[1][0]=fa[2][0]=1;
    		fa[0][n+1]=fa[1][n+1]=fa[2][n+1]=n+1;
    		s1=s2=s3=n+1;
    		fd(i,n,1)
    		{
    			switch (st[i])
    			{
    				case '1':{s1=i;break;}
    				case '4':{s2=i;break;}
    				case '5':{s3=i;break;}
    			}
    			fa[0][i]=s1,fa[1][i]=s2,fa[2][i]=s3;
    		}
    		
    		l=0;H=1;T=0;
    		fo(i,1,n)
    		if (st[i]=='4') ++l;
    		else
    		if (st[i]=='5')
    		{
    			--l;
    			while (T && D[T][1]>=l) --T;
    			++T;D[T][0]=i;D[T][1]=l;
    		}
    		
    		s=0;D[++T][1]=n;D[T][0]=0;
    		while (h<=m)
    		{
    			if (h<=t && s<D[H][1])
    			{
    				j=ans[h][3];
    				fo(k,4,5) j=gf(b[k],j),ans[h][k]=j,fa[b[k]][j]=j+1,++j;
    				++h,++s;
    			}
    			else
    			{
    				++t,j=0;
    				fo(k,0,3) j=gf(b[k],j),ans[t][k]=j,fa[b[k]][j]=j+1,++j;
    				if (D[H][0]==ans[t][3]) ++H;
    			}
    		}
    		fo(i,1,m) {fo(j,0,5) printf("%d ",ans[i][j]);printf("
    ");}
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    UIControl IOS控件编程 及UITextField的讲解
    ViewPager实现页面切换
    HDU 3788 和九度OJ 1006测试数据是不一样的
    的基本原理的面向对象的--------单个程序员必须查看
    hdu1796 How many integers can you find
    Android数据加载和Json解析——蓝本
    设计管理员表;webservice用于网络安全的高端内提供服务的
    how tomcat works 札记(两)----------一个简单的servlet集装箱
    新秀学习Hibernate——一个简单的例子
    在cocos2d-x在CCTableView使用控制
  • 原文地址:https://www.cnblogs.com/gmh77/p/13292179.html
Copyright © 2011-2022 走看看