10.16考试总结

首先为什么最近疯狂写总结呢,当然是教练要求啊,不能只顾埋头刷题,边捡边掉可不划算。

1. 匹配(100/100)

    题目大意:有一些等个数的黑白点,现在把它们配成一个个点对,定义点距为曼哈顿距离,白点恒在黑点右下。求最小距离和。

       感想:看了一眼,咦,这不是一个定值吗,直接加加减减就出来了嘛,然后就开始怀疑人生了,z这么简单?excuse me'?普及组?然后半个小时过去,还是没想到更“科学”的做法,然后打了上去,然后A了。。。。。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <queue>
# include <cmath>
# include <stack>
# include <algorithm>
using namespace std;
typedef long long ll;
ll Read()
{
	ll i=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
	return i*f;
}
ll n,a,b,x,y,x2,y2;
int main()
{
	
	n=Read();
	for(int i=1;i<=n;++i)
	{
		a=Read(),b=Read();
		x+=a,y+=b;
	}
	for(int i=1;i<=n;++i)
	{
		a=Read(),b=Read();
		x2+=a,y2+=b;
	}
	printf("%I64d\n",(x2-x)+(y-y2));
}
2.玩积木(0/100)

    题目大意:给一个什么东西:0

                                                        1  1

                                                        2   2   2

                                                        3   3   3   3

                                                        4   4   4   4   4 

                                                        5   5   5   5   5   5

    现在把它打乱,现在只能动0,且只能向其左上方,上方,右下方,下方,求最少需要多少次数还原(规定不会超过20次);

    感想:看一眼,搜索?,那应该是暴力把,想了半天,还是觉得是搜索,于是我开始怀疑人生了,半个小时后,突发奇想会不会是dp,于是开始想转移状态,想不出来,最后直接暴力都不想打了,直接交了个随机输出,果不其然0分。正解:搜索!a*,折半都可以,反正直接搜就对了。。。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <queue>
# include <cmath>
# include <stack>
# include <algorithm>
using namespace std;
int Read()
{
	int i=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
	return i*f;
}
const int INF=1e9+7;
const int Map[7][7]={0,0,0,0,0,0,0,
                     0,0,0,0,0,0,0,
                     0,1,1,0,0,0,0,
		     0,2,2,2,0,0,0,
		     0,3,3,3,3,0,0,
		     0,4,4,4,4,4,0,
		     0,5,5,5,5,5,5};
struct node
{
	int x,y;
	node(){}
	node(int x,int y) : x(x),y(y){}
};
int n,m,t,ans,a[10][10];
bool vis[10][10]={false};
node go(node p,int i)
{
	if(i==1) p.x--;
	if(i==2) p.x--,p.y--;
	if(i==3) p.x++;
	if(i==4) p.x++,p.y++;
	return p;
}
inline int judge()
{
	int num=0;
	for(int i=1;i<=6;++i)
	    for(int j=1;j<=i;++j)
	        if(a[i][j]!=Map[i][j]) num++;
     return num;
	
}
inline void DFS(node p,int dep)
{
	if(dep>ans) return ;
	if(judge()==0) 
	{
		ans=min(ans,dep);
		return;
	}
	if(dep+judge()>ans) return;
	for(int i=1;i<=4;++i)
	{
		node now=go(p,i);
		if(now.x>=1&&now.x<=6&&now.y>=1&&now.y<=now.x&&a[now.x][now.y])
		{
			swap(a[p.x][p.y],a[now.x][now.y]);
			DFS(now,dep+1);
			swap(a[p.x][p.y],a[now.x][now.y]);
		}
	}
}
int main()
{

	t=Read();
	while(t--)
	{
		node pos;ans=21;
		for(int i=1;i<=6;++i)
		    for(int j=1;j<=i;++j)
		    {
		    	a[i][j]=Read();
		    	if(a[i][j]==0) pos=node(i,j);
		    }
		memset(vis,0,sizeof(vis));
		DFS(pos,0);
		if(ans!=21) printf("%d\n",ans);
		else printf("too difficult\n");
	}
}
3.字符串(30/100)

    题意:给许多字符串,再与一个字符串s匹配,看看有多少组匹配,m次操作修改s中的一个字符,再次匹配;

    感想:因为前两题的怀疑人生,做这道题只剩半小时了,于是打了个kmp拿了30分走人。正解:ac自动机,每次修改只会影响位置前后最长字符串长度的位置,每次只匹配now-maxlen,now+maxlen,于是ok。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int getint() 
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

int buf[1024];
inline void W(int x){
	if(!x){putchar('0');return ;}
	if(x<0){putchar('-');x=-x;}
	while(x) buf[++buf[0]]=x%10,x/=10;
	while(buf[0]) putchar(buf[buf[0]--]+48);
	return ;
}

const int N=1005;
const int M=1e5+5;
const int L=105;
struct node
{
	int cnt,fail,son[26];
}tr[N*L];
char s[M];
int tot,n,m,mx;

void insert()
{
	int len=strlen(s),po=1;
	mx=max(mx,len);
	for(int i=0;i<len;i++)
	{
		if(!tr[po].son[s[i]-'a'])
			tr[po].son[s[i]-'a']=++tot;
		po=tr[po].son[s[i]-'a'];
	}
	tr[po].cnt++;
}

void buildfail()
{
	int head=0,tail=1;
	static int que[N*L];
	que[tail]=1;
	while(head<tail)
	{
		head++;
		int u=que[head],v,w;
		for(int i=0;i<26;i++)
		{
			v=tr[u].fail;
			while(!tr[v].son[i])v=tr[v].fail;
			v=tr[v].son[i],w=tr[u].son[i];
			if(w)tr[w].fail=v,que[++tail]=w,tr[w].cnt+=tr[v].cnt;
			else tr[u].son[i]=v;
		}
	}
}

int ac_auto(int l,int r)
{
	int po=1,ans=0,tmp;
	for(int i=l;i<=r;i++)
	{
		po=tr[po].son[s[i]-'a'];
		ans+=tr[po].cnt;
	}
	return ans;
}

int main()
{
	
	int pos;char c;
	tot=1;
	for(int i=0;i<26;i++)tr[0].son[i]=1;
	n=getint(),m=getint();
	while(n--)
		scanf("%s",s),insert();
	buildfail();
	scanf("%s",s);
	int len=strlen(s);
	int ans=ac_auto(0,len-1);
	W(ans),putchar('\n');
	while(m--)
	{
		pos=getint();
		pos--;
		for(c=getchar();c<'a'||c>'z';c=getchar());
		int l=max(0,pos-mx),r=min(len-1,pos+mx);
		ans-=ac_auto(l,r);
		s[pos]=c;
		ans+=ac_auto(l,r);
		W(ans),putchar('\n');
	}
	return 0;
}

总结:这天我各种怀疑人生,受不了了,希望noip应该不会这么鬼畜。

                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值