18.4.1 考试解题报告 P71

题目:https://files.cnblogs.com/files/lovewhy/problem.pdf

偷偷摘来dalao题面。

P71
竞赛时间:???? 年?? 月?? 日??:??-??:??

 题目名称 智乃   麻耶 惠 
 名称  kahuucino  zyougamaya nacumegu 
输入   kahuucino.in  zyougamaya.in nacumegu.in 
输出   kahuucino.out   zyougamaya.out nacumegu.out 
每个测试点时限   1秒  1秒 1秒 
内存限制  512MB   512MB  512MB
测试点数目   20  10 10 
每个测试点分值  10  10 
是否有部分分   无  无 无 
题目类型   传统 传统  传统 

              

T1

                          智乃
【题目描述】
    给你N个字符串,你每次可以选择其中一个字符串的一段前缀进行翻转,但是你必须保证这个前缀的长度是偶数。你可以进行无限次这样的操作,并且如果
    两个字符串变得相同的时候,你就可以把这两个字符串都删除掉,问最后最少剩下多少个字符串?
【输入格式】
    第一行一个整数T代表数据组数。
    对于每组数据,第一行一个整数N代表字符串个数。
    接下来N行每行一个字符串。
【输出格式】
    对于每组数据,一行一个整数代表答案。
【样例输入】
  2
  5
  esprit
  god
  redotopc
  odcpoter
  dog
  14
  rats
  live
  stressed
  to
  act
  as
  star
  desserts
  of
  evil
  cat
  sa
  fo
  ot
【样例输出】
  3
  0
【样例解释】
  无。
【数据范围与规定】
  40%的数据,字符串长度不超过8。
  对于100%的数据,1 ≤ T≤ 11,字符串长度不超过50,1 ≤ N ≤ 50。

T1

考场40分暴力:

   开个结构体存字符串,然后bfs里暴力翻转,set判重,记录下来,最后n^4判断能不能消除。

   前40分字符串长度<=8,翻转之后貌似是最多有384个串。

//T1
//这么难的吗???
//........
//暴力搞来一发
//1hour left
//i am so nervous 

//不会写hash啊。。。老写炸。。
//那怎么判重啊/。。。
//Meide 
//trie树?
//hhhh gg 

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

const int N=55;

int T,n;
struct STR
{
    bool flag;
    int len;
    int sum;
    string s;
    string ss[1000];
}str[N];

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

inline void mswap(char &a,char &b)
{
    char c=a;
    a=b;
    b=c;
}

inline string reverse(string s,int a,int b)        //stl的reverse不会用。。 
{
    string tmp=s;
    for(;a<=b;++a,--b)
    {
        mswap(tmp[a],tmp[b]);
    }
//    cout<<"tmp: "<<tmp<<endl;
    return tmp;
}

set<string> ma;
queue<string> que;
void bfs(STR &A)
{
    ma.clear();
    ma.insert(A.s);
    que.push(A.s);
    string now,tmp;
    int len=A.len;
    while(!que.empty())
    {
        now=que.front();
//        cout<<now<<endl;
        que.pop();
        for(int i=2;i<=len;++++i)
        {
            tmp=reverse(now,0,i-1);
            if(ma.count(tmp))
                continue;
            que.push(tmp);
            A.ss[++A.sum]=tmp;
            ma.insert(tmp);
        }
    }
}

int main()
{
    freopen("kahuucino.in","r",stdin);
    freopen("kahuucino.out","w",stdout);
    T=read();
    while(T--)
    {
        n=read();
        int ans=n;
        for(int i=1;i<=n;++i)
            str[i].flag=str[i].sum=0;
        for(int i=1;i<=n;++i)
        {
            cin>>str[i].s;
//            cout<<"aa: "<<str[i].s<<endl;
            str[i].ss[++str[i].sum]=str[i].s;
            str[i].len=str[i].s.length();
            bfs(str[i]);
        }
        bool flag;
//        printf("%d",str[1].sum);
        for(int i=1;i<=n;++i)
        {
            if(str[i].flag)
                continue;
            for(int j=i+1;j<=n;++j)
            {
                if(str[j].flag||str[i].len!=str[j].len)
                    continue;
                flag=0;
                for(int k=1;k<=str[i].sum;++k)
                {
                    for(int l=1;l<=str[j].sum;++l)
                    {
                        if(str[i].ss[k]==str[j].ss[l])
                        {
                            flag=1;
                            str[i].flag=str[j].flag=1;
                            ----ans;
                            break;
                        }
                    }
                    if(flag)
                        break;
                }
                if(flag)
                    break;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
40分暴力
// luogu-judger-enable-o2
//T1 正解
//为什么这么6的呢
//stl好用又简洁 
//...代码真短 

//因为不管怎么翻转,原串中挨着的两个字符第i和i+1个总挨在一起
//所以我们把原串分解成很多两个字母的组合
//让组合中的第一个字符的字典序<=第二个字符
//然后,把这好几个组合按字典序排序
//再把它们按排完序后的顺序组合起来
//set判断
//如果这个字符串以前出现过,那么就消掉,余下的字符串数量-2
//否则就扔进set里

//貌似好简单的对吧 
//但是为什么就想不到呢
//只想着打暴力了
//想也不定能想出来 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;

const int N=55;

int T,n;
set<string> se;
string S[N];
string s[N];
string tmp;

inline int work()
{
    int len,ans=n;
    se.clear();
    for(int i=1;i<=n;++i)
    {
        len=S[i].length();
        for(int j=0;j*2<len;++j)
        {
            char x=S[i][j<<1],y=S[i][j<<1|1];
            if(x>y)
                swap(x,y);
            s[j]=x,s[j]+=y;
        }
        sort(s,s+len/2);
        tmp.clear();
        for(int j=0;j<len/2;++j)
            tmp+=s[j];
        if(len&1)
            tmp+=S[i][len-1];
        if(se.count(tmp))
        {
            se.erase(tmp);
            ----ans;
        }
        else
            se.insert(tmp);
    }
    return ans;
}

string a;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            cin>>S[i];
        printf("%d
",work());
    }
    return 0;
}
正解

 麻耶


【问题描述】
    油库里是幻想乡特有的一种生物。每只油库里都有一个战斗力值和一个能量值。当两只油库里战斗时,总是战斗力值高的一位获胜。获胜者的战斗力值将变
    成(自己的原战斗力值-对手的战斗力值+对手的能量值)。败者将死去。若两者战斗力值一样,则同归于尽。
    思考熊发现了很多油库里,他想知道通过互相战斗之后油库里中战斗力值+能量值最高的一个可能到达多少。你能帮他们求出来吗?(假设除了考察的那只
    油库里之外,其他油库里之间不会发生战斗)
【输入格式】
    第一行是一个整数N,代表当前有多少油库里。
    接下来的N行, 每一行有两个整数u,v, 代表这只油库里的战斗力值和能量值。
【输出格式】
    输出一个整数,代表油库里中战斗力值+能量值最高的一个能达到多少。
【样例输入】
  2
  1 2
  2 1
【样例输出】
  4
【样例解释】
  无。
【数据规模与约定】

数据点编号 N = 数据点编号 N =
1 2 6 14989
2 984 7 21726
3 6168 8 100000
4 10470 9 100000
5 19168 10 100000

T2

 理解错题意,那些油库里不一定要死。十分。。。也很多吧。

  天气炎热,不想改题。。

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

const int N=1e5+5;

int n;
long long ans,sum;
struct Yuk
{
    int u,v;
    bool operator < (const Yuk &a) const
    {
        return this->u==a.u?this->v>a.v:this->u<a.u;
    }
}yuk[N];

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar());
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

int main()
{
    n=read();
    for(int i=1;i<=n;++i)
    {
        yuk[i].u=read(),yuk[i].v=read();
    }
    sort(yuk+1,yuk+n+1);
    for(int i=1;i<=n;++i)
    {
        ans=max(ans,sum+yuk[i].u+yuk[i].v);
        if(yuk[i].u<yuk[i].v)
            sum+=yuk[i].v-yuk[i].u;
    }
    printf("%lld",ans);
    return 0;
}
View Code


【问题描述】
    现在你要实现一个文件系统,支持以下操作
      cd Directory_Name
      如果当前路径下有名为 Directory_Name 的文件夹,则进入该文件夹所对应的路径,否则输出“No such directory!” 。
      cd ..
      如果当前路径存在父路径, 则返回父路径, 否则输出 “No parent directory!” 。
      touch File_Name
      如果当前目录下存在名为 File_Name 的文件则输出“File already exists!” ,否则创建这样一个文件。
      rm File_Name
      如果当前目录下存在名为 File_Name 的文件则删除它,否则输出“No suchfile!” 。
      mkdir Directory_Nam e
      如果在当前路径下存在名为 Directory_Name 的文件夹,则输出“Directoryalready exists!” ,否则创建这样一个文件夹(当前路径不变) 。
      rmdir Directory_Name
      如果在当前路径下存在名为 Directory_Name 的文件夹,则删除之,否则输出“No such directory!” 。
      ls
      列出当前路径下所有的文件和文件夹,每一项占一行,按创建的先后顺序给出。采用以下形式输:
        “Item_Name Type”    (Type 为 <D>(文件夹)或<F>(文件))
    注意:同一路径下文件与文件夹可以同名,但同一路径下文件与文件、文件夹与文件夹不能同名。
    初始时当前路径处于根路径下,无父路径。

【输入格式】
    第一行为Q,表示有Q个操作。
    接下来是Q行,每行输入为以上描述的操作之一。

【输出格式】
    输出答案。
【样例输入】
  3
  mkdir standy
  touch totalfrank
  ls
【样例输出】
  standy <D>
  totalfrank <F>
【样例解释】
  无。
【数据规模与约定】
  对于100%的数据,1 ≤ Q ≤ 100,所有文件名字长度不超过200且均为小写字母。

T3

 模拟

//耗我两个半小时。。made
//写麻烦了,可以不开队列直接搞的
//没时间改了。。
//万一TLE
//那就很TM了吧 

//跑得真慢
//样例都这么慢
//等着翻车
//别翻车啊... 

//竟然A了。。。
//又长又丑的代码 
//懒得改它了。 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
using namespace std;

const int N=505;

int Q;
struct F
{
    bool flag;
    int tim;
    string name;
}file[N];
struct D
{
    bool flag;  //这个文件夹还在不在 
    int tim;    //文件夹创建时间 
    string name;    //文件夹名字 
    D *fa;        //父亲path 
    D *wjj[N];        //sons
    F *wj[N];    //file postions
    int s1,s2;    //sum of dires and files
    D *q1[N];
    F *q2[N];
    int h1,h2,t1,t2;
}dir[N<<1],Root;

typedef D* W;
W null,now_d,now;
string opt,name;

typedef F* H;
H now_f;

inline void init()
{
    now_f=file;
    now_d=dir;
    now=&Root;
    now->h1=now->h2=1;
    now->t1=now->t2=0;
    now->fa=null;
    now->flag=1;
    now->name="Root";
}

bool flag=0;
W t1;
H t2;
int main()
{
    freopen("nacumegu.in","r",stdin);
    freopen("nacumegu.out","w",stdout);
    init();
    scanf("%d",&Q);
    for(int i=1;i<=Q;++i)
    {
        cin>>opt;
//        cout<<opt<<endl;
        if(opt=="ls")
        {
//            cout<<now->t1<<" "<<now->t2<<endl;
//            cout<<now->h1<<" "<<now->h2<<endl;
            while(1)
            {
                if(now->h1>now->t1||now->h2>now->t2)
                    break;
                t1=now->q1[now->h1],t2=now->q2[now->h2];
                if(t1->flag==0)
                {
                    ++(now->h1);
                    continue;
                }
                else if(t2->flag==0)
                {
                    ++(now->h2);
                    continue;
                }
                if(t1->tim<t2->tim)
                {
                    cout<<t1->name<<" <D>"<<'
';
                    ++(now->h1);
                }
                else
                {
                    cout<<t2->name<<" <F>"<<'
';
                    ++(now->h2);
                }
            }
            while(now->h1<=now->t1)
            {
                t1=now->q1[now->h1];
                if(!t1->flag)
                {
                    ++(now->h1);
                    continue;
                }
//                printf("%s <D>
",now->q1[now->h1]->name);
                cout<<t1->name<<" <D>"<<'
';
                ++(now->h1);
            }
            while(now->h2<=now->t2)
            {
                t2=now->q2[now->h2];
                if(!t2->flag)
                {
                    ++(now->h2);
                    continue;
                }
//                printf("%s <F>
",now->q2[now->h2]->name);
                cout<<t2->name<<" <F>"<<'
';
                ++(now->h2);
            }
            now->h1=now->h2=1;
            continue;
        }
        cin>>name;
//        cout<<opt<<" "<<name<<endl;
        if(opt=="cd")
        {
            if(name=="..")
            {
                if(now->fa==null)
                    puts("No parent directory!");
                else
                    now=now->fa;
            }
            else
            {
                flag=0;
                for(int j=1;j<=now->s1;++j)
                {
                    if(now->wjj[j]->flag&&now->wjj[j]->name==name)
                    {
                        now=now->wjj[j];
                        flag=1;
                        break;
                    }
                }
                if(!flag)
                    puts("No such directory!");
            }
        }
        else if(opt=="touch")
        {
            flag=0;
            for(int j=1;j<=now->s2;++j)
            {
                if(now->wj[j]->flag&&now->wj[j]->name==name)
                {
                    flag=1;
                    break;
                }
            }
            if(!flag)
            {
                ++now_f;
                now_f->flag=1;
                now_f->tim=i;
                now_f->name=name;
                now->wj[++now->s2]=now_f;
                now->q2[++now->t2]=now_f;
            }
            else
                puts("File already exists!");
        }
        else if(opt=="rm")
        {
            flag=0;
            for(int j=1;j<=now->s2;++j)
            {
                if(now->wj[j]->flag&&now->wj[j]->name==name)
                {
                    flag=1;
                    now->wj[j]->flag=0;
                    now->wj[j]->name="";
                    break;
                }
            }
            if(!flag)
                puts("No such file!");
        }
        else if(opt=="mkdir")
        {
            flag=0;
            for(int j=1;j<=now->s1;++j)
            {
                if(now->wjj[j]->flag&&now->wjj[j]->name==name)
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
                puts("Directory already exists!");
            else
            {
                ++now_d;
                now_d->tim=i;
                now_d->fa=now;
                now_d->name=name;
                now_d->flag=1;
                now_d->h1=now_d->h2=1;
                now_d->t1=now_d->t2=0;
                now->wjj[++now->s1]=now_d;
                now->q1[++now->t1]=now_d;
            }
        }
        else if(opt=="rmdir")
        {
            flag=0;
            for(int j=1;j<=now->s1;++j)
            {
                if(now->wjj[j]->flag&&now->wjj[j]->name==name)
                {
                    flag=1;
                    now->wjj[j]->flag=0;
                    now->wjj[j]->name="";
                    break;
                }
            }
            if(!flag)
                puts("No such directory!");
        }
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
/*
20
mkdir 123
cd 123
rm 123
cd ..
rm 123
rmdir 12
rmdir 123
cd 123
ls
*/

/*
20
cd ..
mkdir 123
mkdir 456
mk 123
mk 456
ls
touch 123
touch 456
ls
rmdir 456
mkdir 456
ls
cd 123
ls
touch mhe
touch why
cd ..
ls
*/
View Code

  做题顺序:

    T1好难啊,不会。

    T2好难啊,不会。

    T3..模拟?。。好像很有意思,做一下。

    T3 2.5h做完,给写的太麻烦了,可以很简洁的写完的。然后T2拿第一个点,然后剩下一小时搞T1,最后10min赵老师来让着交题,但我还没写完。然后继续强搞,在最后10min成功拿下T1的40分暴力分。  但是T2理解错题意,那10分并没有拿到。

   得分:

      T1 40

      T2 0

      T3 100

      Sum 140

  。。。。感觉这几天考的三场试都rp大爆发啊。但是今天的题目貌似并不难,可就是不会做。大概我深受一看不会就打暴力思想的影响吧,毕竟以前吃了考试老想正解不打暴力的很大的亏。但是一看不会就打暴力确实太暴力了。T2应该可以想出来的,但是T3模拟太耗了。         为什么总是不能比较让自己满意地做一套题呢。

原文地址:https://www.cnblogs.com/lovewhy/p/8687840.html