Problem A: 贪吃蛇
Time Limit: 2000 ms Memory Limit: 512 MB
Description
Input
Output
Sample Input
【样例输入1】
4 5
##...
..1#@
432#.
...#.
【样例输出1】
4
【样例输入2】
4 4
#78#
.612
.543
..@.
【样例输出2】
6
【样例输入3】
3 2
3@
2#
1#
【样例输出3】
-1
HINT
Solution
没什么好讲的了吧。暴力就好了。
#include<bits/stdc++.h>
using namespace std;
int mapn[16][16];
const int movex[4]={0,1,0,-1};
const int movey[4]={1,0,-1,0};
struct snake{
int x,y;
}s[10];
int sum[16][16];
int ans=1e9;
int dx,dy;
int len=0;
void dfs(int x1,int y1,int now){
//if(x1==dx&&y1==dy)cout<<now<<endl;
if(now>=sum[x1][y1])return;
sum[x1][y1]=now;
if(x1==dx&&y1==dy){
if(now<=ans)ans=now;
return;
}
for(int i=0;i<4;++i){
int x=x1+movex[i],y=y1+movey[i];
//if(x==14&&y==7)cout<<mapn[x][y]<<endl;
if(mapn[x][y]){
snake tmp=s[len];
for(int i=len;i>=2;--i)s[i]=s[i-1];
s[1]={x,y};
mapn[s[len].x][s[len].y]=1;
mapn[x][y]=0;
dfs(x,y,now+1);
mapn[s[len].x][s[len].y]=0;
mapn[x][y]=1;
for(int i=1;i<len;++i)s[i]=s[i+1];
s[len]=tmp;
}
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=15;++i){
for(int j=1;j<=15;++j)sum[i][j]=1e9;
}
int hx,hy;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
char ch;
cin>>ch;
if(ch=='@'){
mapn[i][j]=1;
dx=i,dy=j;
}
if(isdigit(ch)){
mapn[i][j]=0;
s[ch-'0']={i,j};
}
if(ch=='.'){
mapn[i][j]=1;
}
if(ch=='1'){
hx=i,hy=j;
}
if(isdigit(ch)&&ch-'0'>len){
len=ch-'0';
}
}
}
mapn[s[len].x][s[len].y]=1;
//cout<<len<<endl;
dfs(hx,hy,0);
//for(int i=1;i<=n;++i){
//for(int j=1;j<=m;++j){
//cout<<(sum[i][j]==1e9?0:sum[i][j])<<" ";
//}
//cout<<endl;
//}
printf("%d\n",ans==1e9?-1:ans);
}
Problem B: 字符串
Time Limit: 3000 ms Memory Limit: 1024 MB
Description
UPD:本题字符集为全体小写字母
Input
Output
Sample Input
5
1 abc
3 abcabc
0 abc
3 aba
1 abababc
Sample Output
2
HINT
Solution
把所有的字符串,无论询问还是查询,丢进一个AC自动机里,跑出fail
然后建立fail树。根据fail树的性质,对于一棵以u为根节点的子树,所有子树内的节点所代表的字符串都包含u。
像树剖一样维护fail树,每插入一个就给子树全部出现次数+1 。
查询就是trie树上每个节点的出现次数加起来就好了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct qwq{
int v;
int nxt;
}edge[2000001];
int head[2000001];
int cnt=-1;
void add(int u,int v){
edge[++cnt].nxt=head[u];
edge[cnt].v=v;
head[u]=cnt;
}
struct trie{
int ch[26];
int fail;
}t[2000001];
int tot;
int num[2000001];
void insert(char s[],int id){
int len=strlen(s+1);
int x=0;
for(int i=1;i<=len;++i){
int c=s[i]-'a';
//cout<<c<<endl;
if(!t[x].ch[c]){
t[x].ch[c]=++tot;
}
x=t[x].ch[c];
}
num[id]=x;
}
void getfail(){
queue<int> q;
for(int i=0;i<26;++i){
if(t[0].ch[i]){
t[t[0].ch[i]].fail=0;
q.push(t[0].ch[i]);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;++i){
if(t[u].ch[i]){
//cout<<t[u].fail<<" "<<t[t[u].fail].ch[i]<<endl;
t[t[u].ch[i]].fail=t[t[u].fail].ch[i];
q.push(t[u].ch[i]);
}
else {
t[u].ch[i]=t[t[u].fail].ch[i];
}
}
}
for(int i=1;i<=tot;++i){
//cout<<t[i].fail<<" ";
add(t[i].fail,i);
}
//cout<<endl;
}
int dfn[2000001];
int siz[2000001];
int ind;
void dfs(int u){
dfn[u]=++ind;
siz[u]=1;
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
dfs(v);
siz[u]+=siz[v];
}
}
ll c[2000001];
#define lowbit(x) x&-x
void upd(int x,int v){
while(x<=ind){
//cout<<x<<" ";
c[x]+=v;
x+=lowbit(x);
}
}
int query(int x){
int ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void update(int u,int i){
//cout<<dfn[u]<<" "<<siz[u]<<endl;
upd(dfn[u],i);
upd(dfn[u]+siz[u],-i);
}
int tott;
char s[2000001];
ll solve(int l,int r){
ll ans=0;
int x=0;
for(int i=l;i<=r;++i){
int c=s[i]-'a';
x=t[x].ch[c];
//cout<<x<<" ";
//cout<<dfn[x]<<endl;
ans+=query(dfn[x]);
}
return ans;
}
char a[2000001];
ll opt[2000001];
int st[2000001];
int len[2000001];
int main(){
memset(head,-1,sizeof(head));
int m;
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%lld%s",&opt[i],a+1);
insert(a,i);
len[i]=strlen(a+1);
st[i]=tott+1;
for(int j=1;j<=len[i];++j){
s[++tott]=a[j];
}
}
getfail();
dfs(0);
//for(int i=1;i<=tot;++i)cout<<siz[i]<<" ";
ll mask=0;
for(int i=1;i<=m;++i){
opt[i]^=mask;
if(opt[i]==1){
//cout<<num[i]<<endl;
update(num[i],1);
}
if(opt[i]==2){
update(num[i],-1);
}
if(opt[i]==3){
ll tmp;
//cout<<i<<endl;
printf("%lld\n",tmp=solve(st[i],st[i]+len[i]-1));
mask^=abs(tmp);
}
}
}
Problem C: 都城
Time Limit: 1000 ms Memory Limit: 512 MB
Description
Input
Output
Sample Input
4
1 4
2 4
3 4
Sample Output
2
2
2
3
HINT
Solution
先随意选择一个点,算出这个点如果让它当首都需要改几条边。
然后遍历它的后继,对于这个后继,只需要修改原点到这个后继的这条边就可以满足题目需求了。
然后遍历后继的后继,以此类推就可以了。
用一个vis记录一下每条边的状态就可以知道这条边有没有改了。
#include<bits/stdc++.h>
using namespace std;
int read(){
char ch;
int num=0;
int f=1;
ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
num=num*10+ch-'0';
ch=getchar();
}
return num*f;
}
void out(int num){
if(num>9)out(num/10);
putchar(num%10+'0');
}
struct qwq{
int u1,v1;
int v;
int nxt;
}edge[4000001];
int head[2000001];
int cnt=-1;
void add(int u,int v,int u1,int v1){
edge[++cnt].nxt=head[u];
edge[cnt].v=v;
edge[cnt].u1=u1,edge[cnt].v1=v1;
head[u]=cnt;
}
bool vis[2000001];
int ans[2000001];
void dfs(int u,int fa){
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v,v1=edge[i].v1;
if(v==fa)continue;
if(v1!=v)vis[i]=true,ans[1]++;
dfs(v,u);
}
}
void solve(int u,int fa){
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
if(v==fa)continue;
if(!vis[i])ans[v]=ans[u]+1;
else ans[v]=ans[u]-1;
solve(v,u);
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
memset(head,-1,sizeof(head));
int n;
n=read();
for(int i=1;i<n;++i){
int u,v;
u=read(),v=read();
add(u,v,u,v);
add(v,u,u,v);
}
dfs(1,-1);
solve(1,-1);
for(int i=1;i<=n;++i){
out(ans[i]);
putchar('\n');
}
}