您的位置:首页 > 其它

与不知道什么学ping校ce的ji联zha考le(11.5)

2017-11-05 17:04 316 查看

T1.attack

T2.reverse



分析:

实际上我们是可以倒推出每个状态的前驱

所以我们先把长度长的字符串向前推,直到两个字符串长度相同

之后两个字符串同时向上推,直到达到第一个相同的状态

形象点来说:我们可以把状态集合想象成一棵树,一操作是向左子树走,二操作是向右子树走

我们所求就是两个节点的lca

这道题还涉及字符串hash,还是有点难度的

代码比较丑陋,细节比较多(注意左右端点)

//这里写代码片
#include<cstdio>
#include<cstring>
#include<set>
#define ll long long

using namespace std;

const ll mod=1000000007;
const int N=1005;
const ll x=131;
int len1,len2,l1,l2,r1,r2,L,R;
char s1
,s2
,ans
;
bool ff;
set<ll> S;

int hash(char *s,int l,int r)
{
ll a=0;
if (l<r)
{
for (int i=r;i>=l;i--)
a=a*x+s[i];
if (S.count(a)) return 1;
S.insert(a);
}
else
{
for (int i=r;i<=l;i++)
a=a*x+s[i];
if (S.count(a)) return 1;
S.insert(a);
}
return 0;
}

void doit(char *s,int cnt,int &l,int &r)                     //&l  &r
{
int tt=0;
while (cnt--)
{
if (s[r]=='A')
{
if (r<l) r++; else r--;                          //delete
ff=hash(s,l,r);
if (ff){
if (l<=r){
for (int i=l;i<=r;i++) ans[tt++]=s[i];
}
else{
for (int i=l;i>=r;i--) ans[tt++]=s[i];
}
return;
}
}
else
{
if (r<l) r++; else r--;
swap(l,r);                                        //reverse
ff=hash(s,l,r);
if (ff){
if (l<=r){
for (int i=l;i<=r;i++) ans[tt++]=s[i];
}
else{
for (int i=l;i>=r;i--) ans[tt++]=s[i];
}
return;
}
}
}
}

int main()
{
//freopen("reverse.in","r",stdin);
//freopen("reverse.out","w",stdout);
int T;
scanf("%d",&T);
while (T--)
{
memset(s1,'\0',sizeof(s1));
memset(s2,'\0',sizeof(s2));
memset(ans,'\0',sizeof(ans));
S.clear();

scanf("%s",&s1); scanf("%s",&s2);
if (strcmp(s1,s2)==0) {                    //相等就直接输出
printf("%s\n",s1);
continue;
}

if (strlen(s1)>strlen(s2)) swap(s1,s2);
len1=strlen(s1); len2=strlen(s2);
l1=l2=0; r1=len1-1; r2=len2-1;             //l1,l2,r1,r2左右端点

ff=hash(s1,l1,r1);
ff=hash(s2,l2,r2);

int d=len2-len1;
if (d&&ff==0) doit(s2,d,l2,r2);            //先把两者的长度调整至一致
for (int i=1;i<len1&&ff==0;i++)
{
doit(s1,1,l1,r1);
doit(s2,1,l2,r2);
if (ff) break;
}

if (!ff) printf("-1\n");
else printf("%s\n",ans);
}
return 0;
}


T3.tree



分析:

这就是这道题的精简版





然而今天学校的评测机炸了,这道题我的评测出来都是WA。。。

但是本机也是RE两个点,玄学。。。

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define ll long long

using namespace std;

const int N=100010;
struct node{
int x,y,nxt;
};
node way[N<<1];
int st
,tot=0,n,q,lg;
ll f
,g
;

void add(int u,int w)
{
tot++;
way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
tot++;
way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;
}

void dfs1(int now,int fa)
{
f[now]=0;
for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=fa)
{
dfs1(way[i].y,now);
f[now]=f[now]+f[way[i].y]+1;
}
f[now]=f[now]+1;
}

void dfs2(int now,int fa)
{
ll sum=0;
for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=fa)
sum=sum+f[way[i].y]+1;
if (fa!=-1) sum++;
sum=sum+g[now];               //这种写法可以一并处理根节点这种特殊情况

for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=fa)
{
g[way[i].y]=sum-f[way[i].y];
dfs2(way[i].y,now);
}
}

void dfs3(int now,int fa)
{
g[now]=g[fa]+g[now];

for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=fa)
dfs3(way[i].y,now);
}

int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int u,w;
scanf("%d%d",&u,&w);
add(u,w);
}

dfs1(1,-1);
f[1]=0; g[1]=0;
dfs2(1,-1);
dfs3(1,-1);

for (int i=1;i<=n;i++)
{
printf("%0.3lf\n",(double)g[i]+1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: