机房模拟20180816

 T1

我们基本可以一眼看出,由于我们需要的是26个字母都有,所以说如果要踢掉重复的字母的话,肯定是一个字符串中先进去的那个

所以我们直接O(n)枚举,将扫描到的字符串加入到队列中并在一个桶里面存入字符串中每个字母的数量,然后每当枚举到一个新的元素的时候,我们就可以扫描一遍当前的字串,将如果队首元素数量大于1就将其踢出

复杂度O(26*n);

水水就过去.jpg

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
const int MAXN=2e6+5;
char c[MAXN];
int tong[30];
int len;
int temp[30];
std::queue<int>q;
int main() 
{
    //freopen("str.in","r",stdin);
    //freopen("str.out","w",stdout);
    char ch;
    while(ch<'A' || ch>'Z')
	{
		ch=getchar();
	}
    while(ch>='A' && ch<='Z') 
	{
        c[++len]=ch;
        tong[ch-'A'+1]++;
        ch=getchar();
    }
    bool flag=1;
    for(int i=1;i<=26;i++)
    {
        if(!tong[i]) 
		{
            flag=0;
            break;
        }
    }
    if(!flag) 
	{
        printf("QwQ");
        return 0;
    }
    int ans=len;
	int tl=0;
    for(int i=1;i<=len;i++) 
	{
        q.push(c[i]-'A'+1);
        tl++;
        temp[c[i]-'A'+1]++;
        while(temp[q.front()]>1) 
		{
            temp[q.front()]--;
            tl--;
            q.pop();
        }
        bool check=0;
        if(tl<26) check=1;
        else 
		{
            for(int i=1;i<=26;i++)
            {
                if(!temp[i]) 
				{
                    check=1;
                    break;
                }
            }
        }
        if(!check)
        {
        	ans=std::min(ans,tl);
        }
    }
    printf("%d",ans);
    return 0;
}

T2

#include<bits/stdc++.h>
#define LL long long
int ask(long long x)
{
	LL l=1,r=1e6;
	while(l<r)
	{
		LL mid=(l+r)>>1;
		LL now=mid*mid*mid;
		if(now==x)
		{
			return mid;
		}
		else
		if(l*l*l==x)
		{
			return l;
		}
		else
		if(r*r*r==x)
		{
			return l;
		}
		else
		if(now<x)
		{
			l=mid+1;
		}
		else
		{
			r=mid;
		}
	}
	return 0;
}
int main()
{
	//freopen("game.in","r",stdin);
	//freopen("game.out","w",stdout);
	int T;
	LL a,b;
	std::scanf("%d",&T);
	while(T--)
	{
		scanf("%I64d %I64d",&a,&b);
		LL now=ask(a*b);
		if(now)
		{
			if(a%now==0&&b%now==0)
			{
				printf("Yes\n");
			}
			else
			{
				printf("No\n");
			}
		}
		else
		{
			printf("No\n");
		}
	 } 
	 return 0;
 }

将两个数相乘,看一看是不是一个数的立方,然后两个数除掉这个数,就是两个人分别赢的k的乘积,计算一下是否x*x*y==a和y*y*x==b就行了

然而就是这么浅显的做法,考场上想到了近似正解却写挂了,然后认为自己想法错误就放弃了,写了个骗分算法只苟了10分.......

然后把T3做出来了,然后发现班上有人T3的暴力贪心过了八个点,这个T2真的亏了一个亿.....

 

T3

我们可以发现这道题是二分图的裸题,直接将所有横向的联通块和与其相连的纵向联通快建边,直接跑一边最小点覆盖就行了

最小点覆盖=最大匹配

#include<cstdio>
#include<cstring>
#define LL long long
const int MAXN=2505;
int r,c;
char G[55][55];
int link[2505];
int cover[52][52][52][52];
class Edge
{
	public:
		int nxt;
		int to;
}edge[50005<<1];
int num;
int head[50005];
void add(int from,int to)
{
	edge[++num].nxt=head[from];
	edge[num].to=to;
	head[from]=num;
}
bool b[MAXN];
bool find(int x)
{
	for(int i=head[x];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(!b[v])
		{
			b[v]=1;
			if(link[v]==-1||find(link[v]))
			{
				link[v]=x;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	//std::freopen("cover.in","r",stdin);
	//std::freopen("cover.out","w",stdout);
	std::scanf("%d%d",&r,&c);
	std::scanf("\n");
	for(int i=1;i<=r;i++)
	{
		std::scanf("\n");
		for(int j=1;j<=c;j++)
		{
			G[i][j]=getchar();
		}
	}
	int cnt=0;
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			if(G[i][j]=='*')
			{
				int nowil=i;
				int nowir=i;
				int nowjl=j;
				int nowjr=j;
				while(G[nowil][j]=='*'&&nowil>=1)
				{
					nowil--;
				}
				nowil++;
				while(G[nowir][j]=='*'&&nowir<=r)
				{
					nowir++;
				}
				nowir--;
				if(!cover[nowil][j][nowir][j])
				{
					cover[nowil][j][nowir][j]=++cnt;
				}
				while(G[i][nowjl]=='*'&&nowjl>=1)
				{
					nowjl--;
				}
				nowjl++;
				while(G[i][nowjr]=='*'&&nowjr<=c)
				{
					nowjr++;
				}
				nowjr--;
				if(!cover[i][nowjl][i][nowjr])
				{
					cover[i][nowjl][i][nowjr]=++cnt;
				}
				add(cover[nowil][j][nowir][j],cover[i][nowjl][i][nowjr]);
			}
		}
	}
	int res=0;
	std::memset(link,-1,sizeof(link));
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			for(int t=i;t<=r;t++)
			{
				for(int p=j;p<=c;p++)
				{
					if(cover[i][j][t][p]==0)
					{
						continue;
					}
					if(cover[i][j][t][p])
					{
						std::memset(b,0,sizeof(b));
						if(find(cover[i][j][t][p]))
						{
							res++;
						}
					}
				}
			}
		}
	}
	std::printf("%d\n",res);
	return 0;
}
/*
input
4 4
*.*.
.***
***.
..*.

output
4
input
4 4
.**.
**.*
*.*.
*...

output
5
input
4 4
****
****
****
****
output
4
*/

水的要死.....但是T2真心脑抽最后只有210分..........血亏

猜你喜欢

转载自blog.csdn.net/Amuseir/article/details/81740336