ACM - 基础篇(下)

简介: ACM - 基础篇(下)

50% 占比,小技巧:

// 行数是列数的50%(四舍五入取整)
int n; cin>>n;
int col=n,row=n-n/2;

模仿 split 分割小技巧:

string s="abc 123 . ",ts;
stringstream ss(s);
int k=0;
while(ss>>ts)
{
    k++;
    cout<<ts<<endl;
    cout<<k<<endl;
}

map<string, int> 搭配 scanf:

map<string,int> mp;
char s1[100];
scanf("%s",s1);
mp[s1]=1;
// 容易 TLE
string s2;
cin>>s2;
mp[s2]=1;

翻译:

1、“a by b” // a * b

对于局部数组来讲:如果数组在定义声明顺便初始化的时候,只要前面有数据赋值,多少个都可以,至少有一个即可,则,其后的数组里的元素全部为0,所以一般 int a[100]={0}; 并不是把全部数组元素变为0,而是因为刚刚说的这个原理。如果改成 int a[100]={1,2,3}; 则前3个为1,2,3,但后面都为0。

首尾空格处理 + strncpy:


/

// 首尾空格处理
int l=0,r=k-1;
while(s[l]==' ') l++;
while(s[r]==' ') r--;
strncpy(s,s+l,r-l+1);
ts[r-l+1]=0;

strtok 函数:

char str[] = "I am a  stduent,you are teacher!";
const char spliter[] = " ,!";
char * pch;
pch = strtok( str, spliter );
while( pch != NULL )
{
    cout << pch << endl;
    pch = strtok( NULL, spliter );
}

lower_bound / upper_bound 函数:

/* 数组从 1 开始存储,但是查找的时候依然是从 0 开始,因为若当待查找的数据>最大值,return 数组大小;若<最小值,return 0;而如果不从 1 开始存储的话,当 return 0 时,不知道是查找到第一个数据还是因为没找到的缘故。 */
int l=lower_bound(a,a+n+1,b)-a; // 在 a[i] 中,返回第一个大于等于 b 的数字的对应位置
int r=upper_bound(a,a+n+1,b)-a; // 在 a[i] 中,返回第一个大于 b 的数字的对应位置
int rs=r-l;                     // 表示有 rs 个等于 b 的数

四舍五入到整数小技巧:

printf("%d",(int)(x+0.5)); // 比下面这种写法有时更加精确
printf("%.0f",double(x));

  1. 上下界针对 y轴 来说,所以上界显然大于等于下界,也就是说:区间[下界,上界]。
  2. 进制互转:
/* 10进制转任意进制 */
void D2Any(int x,int r)
{
    int a,b=x,k=0,ans[100];
    while(1)
    {
        a=b%r;
        b=b/r;
        ans[k++]=a;
        if(x/r==0) break;
        x/=r;
    }
    for(k--;k>=0;k--)
    {
        if(ans[k]>9)
            printf("%c",ans[k]+87); // 87:小写,55:大写
        else
            printf("%d",ans[k]);
    }
}
/* 任意进制转10进制 */
ll Any2D(char x[],int r)
{
    int len=strlen(x),tmp=1;
    ll ans=0;
    for(int i=len-1;i>=0;i--)
    {
        if(x[i]>='0' && x[i]<='9')
            ans+=(x[i]-'0')*tmp;
        else
            ans+=(x[i]-'a'+10)*tmp;
        tmp*=r;
    }
    return ans;
}

0.000005 处理精度丢失问题,具体要加多少个“0”,看题目的保留多少位的情况再做分析。

变量的 初始化 和 定义,尽量跟业务逻辑的代码紧挨在一起;先业务逻辑,需要用到的变量再往上面补充。

日期比较 y*10000 + m*100 + d 小技巧。

差分前缀和小技巧:点击打开链接

输入一个十进制,统计它的二进制数中“1”的个数


/

int cnt1(int x)
{
    int cnt=0;
    while(x) cnt++, x=x&(x-1);
    return cnt;
}

输出格式控制:

// 第一种 4 line 每次都要判断相对来说也消耗
for(int i=0;i<n;i++)
    if(i) printf(" %d",a[i]);
    else printf("%d",a[i]);
puts("");
// 第二种 4 line
printf("%d",a[0]);
for(int i=1;i<n;i++)
    printf(" %d",a[i]);
puts("");
// 第三种 3 line
// 最好不要从0开始,否则每次都要 -1 相对来说也要消耗(即使可忽略不计),所以从1开始比较好
for(int i=1;i<n;i++)
    printf("%d ",a[i]);
printf("%d\n",a[n]);
// 第四种 2 line
for(int i=0;i<n;i++)
    printf("%d%c",i==n-1?'\n':' ');

输入格式控制:

char ch;
scanf(" %c", &ch); // 百分号之前有一个空格,这样scanf会首先过滤掉所有的空格、制表符和换行符
/* 常见吸收回车写法 */
char ch;
int n; 
scanf("%d",&n);
getchar();        // 不推荐
scanf("%c",&ch);
scanf("%d",&n);
scanf(" %c",&ch); // 推荐

输入(一行有空格的字符串),希望不包括空格以 '\n' 结束:

/* 用 do-while 免得最后一次数据('\n'前)还要额外处理 */
do
{
    scanf("%s",key);
    nds[i].kv.push_back(key);
}while(getchar()!='\n');

利用格式符 “%[]” 作用:为扫描字符集合:

scanf("%[^c]", str);

其中 “c” 是一个具体的字符常量(包括控制字符)。

C语言中 scanf() 函数提供的 “%[]” 格式串可以用来进行多个字符的输入,并对结束符进行自定义。对于 %[] 还可以用 ^+ 任意字符(包括 eof)来结束字符串的输入,如 %[^EOF] 就是直到有 EOF 输入,字符串才中止。


/

scanf("%[^\n]", str);  // 以换行符作为字符串输入的结束(可包含空格)


针对非升序 / 非降序操作,如果相等按照原来输入的顺序进行排序(通过伪优先级控制):

struct node
{
    int ge,pri;
}nds[100005];
int cmp(node n1,node n2) // 非升序
{
    if(n1.ge==n2.ge) return n1.pri<n2.pri; 
    return n1.ge>n2.ge;
}

自定义进制(模仿 hh: mm: ss)

typedef long long ll;
int main()
{
    ll a1,b1,c1,a2,b2,c2;
    scanf("%lld.%lld.%lld%lld.%lld.%lld",&a1,&b1,&c1,&a2,&b2,&c2);
    ll rs=c1+b1*29+a1*17*29+c2+b2*29+a2*17*29;
    // rs(秒)    hh=rs/3600    mm=rs%3600/60    ss=rs%60
    printf("%lld.%lld.%lld\n",rs/(17*29),rs%(17*29)/29,rs%29);
    return 0;
}

大数比较小技巧点击打开链接


double 判 0 小技巧:

double A; scanf("%lf",&A);
if(A+0.005>=0&&A<0) printf("0.00"); // 1
if(fabs(A)<0.0005) printf("0.00");  // 2 推荐

矩阵区分八个方向是【越界】or【题目条件】的区分小技巧:

int pas=1, k=0; // 这里 pas 不能从 0 开始,否则会影响判断
if(i-1>=0 && pas++ && abs(a[i-1][j]-d)>st) k++;
if(i-1>=0 && j+1<m && pas++ && abs(a[i-1][j+1]-d)>st) k++;
if(i-1>=0 && j-1>=0 && pas++ && abs(a[i-1][j-1]-d)>st) k++;
if(j-1>=0 && pas++ && abs(a[i][j-1]-d)>st) k++;
if(j+1<m && pas++ && abs(a[i][j+1]-d)>st) k++;
if(i+1<n && pas++ && abs(a[i+1][j]-d)>st) k++;
if(i+1<n && j-1>=0 && pas++ && abs(a[i+1][j-1]-d)>st) k++;
if(i+1<n && j+1<m && pas++ && abs(a[i+1][j+1]-d)>st) k++;
if(k+1==pas) return 1;

有时候创建数据结构的情况比较复杂的时候,先不要急于创建,可以在思路Coding的过程中,发现需要用到哪个变量就创建哪个变量。

判断语句原则:先判断再决定;而不是先决定再判断。

数组初始化的三种常用方法:for循环浪费的时间最多,{0} 与 memset 耗时差不多。

PAT的题目因为时间控制严格,而且它评测机制每次都一个测试用例一次,所以不到万不得已,不要像平常ACM一样去做清空操作。

heap:


// 边插入边建堆
for(int i=1;i<=n;i++)
{
    scanf("%d",&a[i]);
    make_heap(a+1,a+1+i,greater<int>()); // min heap
}
// 先建树再调整堆
make_heap(a,a+n); // max heap

区间合并小技巧:点击打开链接


在DFS中途就可以输出结果并且结束整个程序技巧

exit(0);
  1. '\0' 输出不是什么都没有,而是一个类似的空格,当它用 %c 单独输出时。
  2. 待更新...
目录
相关文章
|
5月前
|
机器学习/深度学习 C++
程序与技术分享:2017ACM
程序与技术分享:2017ACM
26 0
|
Java C语言 C++
ACM刷题之路(二)谈谈我对ACM的理解
ACM刷题之路(二)谈谈我对ACM的理解
118 0
|
Java Android开发
ACM刷题之路(七)字符串处理 记元培ACM院赛
ACM刷题之路(七)字符串处理 记元培ACM院赛
|
算法 编译器 C++
ACM - 基础篇(上)
ACM - 基础篇(上)
196 0
|
算法
ACM模板——快速模幂算法
ACM模板——快速模幂算法
119 0
|
算法
All Of ACM
数据结构和算法专栏,我会什么写什么  = = 不定时更新 一、数据结构 树状数组详解 线段树详解 二、算法 KMP算法 三、板子 我的代码模板 大整数模板
690 0
|
机器学习/深度学习 人工智能 自然语言处理
独家对话AAAI、ACM、ACL三会会士Raymond J. Mooney | 香侬专栏
德克萨斯大学奥斯汀分校计算机系教授、人工智能实验室主任 Raymond J. Mooney 带领他的人工智能小组研究了多个领域,目前他的主要研究方向是自然语言处理和计算语言学。其本人曾在 2008-2011 年间担任国际机器学习协会(ICML 主办方)主席,曾多次担任 ICML、ACL、AAAI、EMNLP、NAACL 等会议主席或领域主席,现在为美国计算机学会(ACM)、国际人工智能学会 (AAAI)、国际计算语言学会(ACL)三会会士 。
2478 0
|
机器学习/深度学习
|
机器学习/深度学习 C++