Coderforces Round #296(DIV.2)

Coderforces 296 Div2
A题背景:竟然没有考虑到数据有1e12这么大,中间应该用取余代替频繁的加减,比如30和3,就不用频繁的减三了,直接取余3即可!

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define M 1009
#define INF 1e9
#define LL long long int
using namespace std;




int main(void){
    LL count=0,a,b;
    scanf("%I64d%I64d",&a,&b);
    while(true){
        if(a < b) swap(a,b);
        if(b == 0) break;
        if(a == b) {count++;break;}
        if(b==1){count+=a;break;}
        count+=a/b;
        a=a%b;
    }
    printf("%I64d",count);
    return 0;
}


B题:一道思想很巧妙的题,暴力方法O(n^2)超时,用set优化了查找之后O(nlogn)超时,最后无计可施看答案。。。

思路:这个最大的巧妙点是字符串虽然可以很长,但是元素是由小写字母组成的只有26种,而上下不相同的字母组成最多只有26*26种,所以用一个C[26][26]来记录每一种可能不同字母对出现的位置,这样如果有C[i][j],C[j][i]同时存在,就可以达到减少两个的效果了。

我的代码:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#define M 200009
#define INF 1e9
using namespace std;
char str1[M],str2[M];
int A[26],B[26],C[26][26];

int main(void){
    int n,ans=0;
    scanf("%d%s%s",&n,str1,str2);
    for(int i=0;i < n;i++)
        if(str1[i] != str2[i])
            ans++,A[str1[i]-'a']=i+1,B[str2[i]-'a']=i+1,C[str1[i]-'a'][str2[i]-'a']=i+1;
    for(int i=0;i <26;i++){
        for(int j=0;j < 26;j++){
            if(C[i][j] && C[j][i]){
                printf("%d\n%d %d\n",ans-2,C[i][j],C[j][i]);
                return 0;
            }
        }
    }
    for(int i=0;i < 26;i++) if(A[i] && B[i]){printf("%d\n%d %d\n",ans-1,A[i],B[i]);return 0;}
    printf("%d\n-1 -1\n",ans);
    return 0;
}
C题:背景:比赛的时候暴力模拟O(n^2)的算法果断超时,只是对set用的不熟,后来看了别人用set做出来的,也就写了,鉴于set和map都是十分高效的数据结构虽然自己还写不出来


,学会用STL也是好的。
然后新知道的一些知识:
equal_range(v)函数返回一个pair类型,first为大于或等于v的第一个数,second为大于v的第一个数//类似于同时使用lower_bound(key_value),upper_bound(key_value)可以来高
效的查找。
iterator类不能减一,可以自增自减。
思路:用两个set来储存长和高的断点,两个multiset来储存长和高的长度(因为可能出现多个长度相同的点),这样进行模拟即可。这里有一点值得注意的地方:multiset进行


erase(key_value)操作时,是删除所有该值!
易错:
int a=INF,b=10000;
LL x=a*b;//这个是错误的,表达式右边全是int,不会因为赋值左边是LL而高级化。
我的代码:

#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define M 10
#define INF 0x3fffffff
#define LL long long int
using namespace std;




int main(void){
    int length,width,t;
    scanf("%d%d%d%*c",&length,&width,&t);
    set<int,greater<int> > l,w;
    l.insert(0);
    l.insert(length);
    w.insert(0);
    w.insert(width);
    multiset<int,greater<int> > ml,mw;
    ml.insert(length);
    mw.insert(width);
    set<int,greater<int> >::iterator it_set1,it_set2,it_set3;
    multiset<int,greater<int> >::iterator it_multiset1,it_multiset2;
    while(t--){
        char c;
        int x;
        scanf("%c %d%*c",&c,&x);
        if(c == 'H'){
            w.insert(x);
            it_set2=it_set1=it_set3=w.find(x);
            it_set1--;
            it_set2++;
            it_multiset1=mw.find(*it_set1-*it_set2);
            mw.erase(it_multiset1);
            mw.insert(*it_set1-*it_set3);
            mw.insert(*it_set3-*it_set2);
        }else{
            l.insert(x);
            it_set2=it_set1=it_set3=l.find(x);
            it_set1--;
            it_set2++;
            it_multiset1=ml.find(*it_set1-*it_set2);
            ml.erase(it_multiset1);
            ml.insert(*it_set1-*it_set3);
            ml.insert(*it_set3-*it_set2);
        }
        it_multiset1=ml.begin();
        it_multiset2=mw.begin();
        //cout << ml.count(2) << endl;
        //cout << *it_multiset1 << "   " << *it_multiset2 << endl;
        LL a=(LL)*it_multiset1;
        LL b=(LL)*it_multiset2;
        LL xx=a*b;
        printf("%I64d\n",xx);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值