首先为什么最近疯狂写总结呢,当然是教练要求啊,不能只顾埋头刷题,边捡边掉可不划算。
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应该不会这么鬼畜。