夜色已经很晚了,所以我长话短说

1.表单

 

链接:https://ac.nowcoder.com/acm/contest/917/C
来源:牛客网

输入描述:

第一行两个整数n,Q

后n行每行一个字符串

后Q行每行代表一个操作:

一操作:1 s

二操作:2

输出描述:

对于每个二操作,进行回答。
示例1

输入

复制
4 4
play
the
pubg
game
1 game
1 pubg
2
2

输出

复制
2
0

说明



100% 1n,Q5×105100% 1≤n,Q≤5×105
 
对于所有输入的字符串长度<=40


这个链接不错,让我在做题的时候启蒙了
https://blog.csdn.net/zhaohuaonline/article/details/21482687

这道题之前觉得4 4 这种输入也没啥用,结果开始编程直接没编进去,打算结束的时候往里加,结果忘了,由此带来的退出循环问题耗时耗力影响了解题进度。下次首先1.把输入的格式先写好2.尽量看清能给的条件,团结一切可以团结的力量。

莫名其妙flag每次结尾置0导致报错

cin换成scanf提高正确率

以上两点都是编译器自己sb

对map的循环不能放在循环里,会超时,这个值得注意

下面放出我期待已久的map以及迭代器的用法,真的是太方便了,鸟枪换炮感觉就是不一样!!开森(/≧▽≦)/

map<string,int> word_count;
map<string,int>::iterator iter;
//输入字符串进map
 for(int i=0;i<a1;i++)
    {
        cin>>word;
        ++word_count[word];
    }
//对map进行遍历,并对数值进行操作
 for(iter = word_count.begin(); iter != word_count.end(); iter++)
    {
        res+=(iter->second-1);
        iter->second=1;
    }

这道题在思路上有一个改进点:

核心本题是求,字符重复的次数,我一直觉得得把map中的次数统计部分,数数,开始还为此发愁,后来直接遍历的时候每个减1,就是重复次数了

但,其实还有更好方法。用

if(flag==1)
            {

                cin>>word;
//if括号里面的内容,运用了map的属性,如果这个词之前没有出现过,查无此人,则一定会
//是false,这种情况就说明出现了重复,用一个单独的变量统计重复的次数,只在这个时候
//++即可减轻了计算负担
                if(word_count[word]) res++;
                else word_count[word]=1;
                flag=0;
            }

下面放出我的解法:

#include<iostream>
#include<math.h>
#include<map>
#include <string>
#include<stdio.h>
#include <cstdlib>
using namespace std;
int main()
{
    map<string,int> word_count;
    map<string,int>::iterator iter;
    string word;
    int flag=-1;
    int res=0;
    int a1,a2;
    //scanf("%d %d",&a1,&a2);
    cin>>a1>>a2;
    for(int i=0;i<a1;i++)
    {
        cin>>word;
        ++word_count[word];
    }
    for(iter = word_count.begin(); iter != word_count.end(); iter++)
    {

        res+=(iter->second-1);
        iter->second=1;
    }

    for(int i=0;i<a2;i++)
    {
        //cout<<"flag:"<<flag<<endl;
        scanf("%d",&flag);
        //cout<<"flag1:"<<flag<<endl;
        //cin>>flag;

        if(flag==1)
            {

                cin>>word;
                if(word_count[word]) res++;
                else word_count[word]=1;
       
            }
        else
            {

                cout<<res<<endl;
                 res=0;
           

            }
    }
    return 0;
}

真正大佬的代码,看看什么叫信达雅

//膜大佬
#include<bits/stdc++.h>
using namespace std;
int n,q,res;
map<string,int> mp;
int main()
{
    scanf("%d %d",&n,&q);
    while(n--)
    {
        string str;
        cin>>str;
        if(mp[str]) res++;
        else    mp[str]=1;
    }
    while(q--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            string str;
            cin>>str;
            if(mp[str]) res++;
            else    mp[str]=1;
        }
        else
        {
            printf("%d\n",res);
            res=0;
        }
    }
    return 0;
}

 2.pow慎用

尤其是先开完方再平方就容易有问题

int main()
{
    int n=100;
//如果是double的,结果还可以是100,如果是int型,结果是99,估计是精度造成的,但下
//次注意不要用pow,比较好的解决方式是直接乘,t*t,反正只用乘一次,但稳定性和正确
//率都会高很多
    double t=sqrt(n);
    cout<<t<<endl;
    double k=pow(t,2);
    cout<<k<<endl;
    return 0;
}

3.

特别注意一个思想上的问题

有些需要循环统计次数的问题,如果有一个全局变量计数,每次循环之前记得要清0

求公因子这次至少有两道题,直接遍历的方法很容易超时,这里介绍一种辗转相除法

例1 。求两个正数8251和6105的最大公因数。
(分析:辗转相除→余数为零→得到结果)
解:8251=6105×1+2146
显然8251与6105的最大公因数也必是2146的因数,同样6105与2146的公因数也必是8251的因数,所以8251与6105的最大公因数也是6105与2146的最大公因数。
6105=2146×2+1813
2146=1813×1+333
1813=333×5+148
333=148×2+37
148=37×4+0
则37为8251与6105的最大公因数。
以上我们求最大公因数的方法就是辗转相除法。也叫欧几里德算法,它是由欧几里德公元前300年左右首先提出的。

int gcd1(int a,int b)
{
  int  temp;
  if(a==0||b==0)
   return -1;
  if(a<b)
    { temp=a;a=b;b=temp;} //求最小值最大值,大的用a表示,小的用b表示
   while(b!=0)            //用循环求最大公约数
    {
      temp=a%b;
      a=b;
      b=temp;
    }
  if(a==1)
    return -1;
  return a;              //返回最大公约数
}

 

posted on 2019-06-15 00:55  黑暗尽头的超音速炬火  阅读(187)  评论(0编辑  收藏  举报