CF #345 Div. 2

1 篇文章 0 订阅
1 篇文章 0 订阅

CF #345 Div. 2

@(codeforces)[CHC]

《Alive》

A. Joysticks

有两个游戏柄和一个充电器,初始时两个游戏柄的电量分别为a%和b%,某个游戏柄如果连接充电器的话每分钟可以提升1%的电量,如果不连接充电器每分钟掉2%的电量,如果某游戏柄的电量<=0就不能玩。问最多能玩多久?
1a1,a2100

输入:
1 1
输出:
0
输入:
3 5
输出:
6
输入:
4 4
输出:
5

.
.
.
.
.
.
.
.
.
范围小。。枚举。。策略是贪心。。哪个电量少就给哪个充电。。

//author: CHC
//First Edit Time:  2016-03-12 11:29
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=1e+4;
const int MAXM=1e+5;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();

int main()
{
    int a,b;
    while(~scanf("%d%d",&a,&b)){
        int ans=0;
        while(a>0&&b>0){
            if(a<b)swap(a,b);
            ++ans;
            b++;
            a-=2;
            if(a<0)--ans;
            //printf("%d %d\n",a,b);
        }
        printf("%d\n",ans);
    }
    return 0;
}

扩展

如果数据量大,就是不用枚举或者单位为毫秒或者微秒。。 1a,b1010 怎么求?

B. Beautiful Paintings

给一个长度为n( 1n1000 )的数组,对于每个数字 1ai1000 ,把这个数组的顺序重新组合后求最多有多少对 ai1<ai
输入:
5
20 30 10 50 40
输出:
4
输入:
4
200 100 100 200
输出:
2
.
.
.
.
.
.
.
.
.
.
范围小。。哈系,枚举。。

//author: CHC
//First Edit Time:  2016-03-12 13:05
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=1e+4;
const int MAXM=1e+5;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
int has[1010];
int n;
int main()
{
    while(~scanf("%d",&n)){
        memset(has,0,sizeof(has));
        for(int i=0,x;i<n;i++){
            scanf("%d",&x);
            ++has[x];
        }

        int ans=0;
        for(int i=0;i<1000;i++){
            int cnt=0;
            for(int j=1;j<=1000;j++){
                cnt+=(has[j]>0);
                has[j]--;
            }
            if(cnt<=1)break;
            ans+=cnt-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

扩展

如果范围很大,不能使用枚举该如何做?

C. Watchmen

在二维平面上,有n个点( 1n200000 ),问有多少对点(i,j)( i<j )可以使得以下成立
|xixj|+|yiyj|=(xixj)2+(yiyj)22
|xi|,|yi|109

输入:
3
1 1
7 5
1 5
输出:
2
输入:
6
0 0
0 1
0 2
-1 1
0 1
1 1
输出:
11

.
.
.
.
.
.
.
.
.
.
.
.
计算某行的组合+某列的组合-自己和自己的组合

//author: CHC
//First Edit Time:  2016-03-12 13:26
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=200000+100;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
struct point {
    int x,y;
}cs[MAXN];
int cmp(const point &x,const point &y)
{
    if(x.x!=y.x)return x.x<y.x;
    return x.y<y.y;
}
int A[MAXN*2];
int n;
int tmp[MAXN*2];
int main()
{
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            scanf("%d%d",&cs[i].x,&cs[i].y);
            A[i<<1]=cs[i].x;
            A[i<<1|1]=cs[i].y;
        }
        sort(A,A+(n<<1));
        int tn=unique(A,A+(n<<1))-A;
        memset(tmp,0,sizeof(tmp));
        for(int i=0;i<n;i++){
            int pos = lower_bound(A,A+tn,cs[i].x)-A;
            ++tmp[pos];
        }
        LL ans = 0;
        for(int i=0;i<n;i++){
            int pos = lower_bound(A,A+tn,cs[i].x)-A;
            if(tmp[pos]){
                //printf("x:%d %d\n",cs[i].x,tmp[pos]);
                ans += 1LL*(tmp[pos]-1)*tmp[pos]/2;
                tmp[pos]=0;
            }
        }
        for(int i=0;i<n;i++){
            int pos = lower_bound(A,A+tn,cs[i].y)-A;
            ++tmp[pos];
        }
        for(int i=0;i<n;i++){
            int pos = lower_bound(A,A+tn,cs[i].y)-A;
            if(tmp[pos]){
                //printf("y:%d %d\n",cs[i].y,tmp[pos]);
                ans += 1LL*(tmp[pos]-1)*tmp[pos]/2;
                tmp[pos]=0;
            }
        }
        //printf("%lld\n\n",ans);
        sort(cs,cs+n,cmp);
        int cnt=1;
        int tx=cs[0].x,ty=cs[0].y;
        for(int i=1;i<n;i++){
            //printf("h:%d %d\n",cs[i].x,cs[i].y);
            if(tx==cs[i].x&&ty==cs[i].y){
                ++cnt;
                //printf("%d %d %d\n",cs[i].x,cs[i].y,cnt);
            }
            else {
                ans-=1LL*(cnt-1)*cnt/2;
                cnt=1;
                tx=cs[i].x;ty=cs[i].y;
            }
        }
        ans-=1LL*(cnt-1)*cnt/2;
        printf("%lld\n",ans);
    }
    return 0;
}
/*
 * #1 : 越界
 * */

D.

有n张图片在手机里( 1n5105 ),看一张图片需要1秒,看相邻的图片需要左划或者右划,左划或者右划需要a秒,旋转一张图片需要b秒,手机是竖着的,有的图片需要横着看,不能旋转手机,只能旋转图片,如果一张图片看过,那么再次看它会被忽略,一开始打开手机看到的是第一张图片
给n,a,b,T,问最多能看多少张图片

输入:
4 2 3 10
wwhw
输出:
2
输入:
5 2 4 13
hhwhh
输出:
4
输入:
5 2 4 1000
hhwhh
输出:
5
输入:
3 1 100 10
whw
输出:
0

.
.
.
.
.
.
.
.
.
.
.
只有四种情况:
1. 从第一张一直往右边看
1. 从第一张一直往左边看
1. 从第一张先往左边看,再往右边看
1. 从第一张先往右边看,再往左边看
只需要固定一个点,然后二分求就可以了复杂度 O(nlogn) 。。注意这里如果不预处理,复杂度会退化成 O(n2logn)

//author: CHC
//First Edit Time:  2016-03-12 19:30
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=500000 * 2 + 1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
int n,a,b,T;
char str[MAXN];
LL pre[MAXN];
LL Calc(int l,int r){
    LL cnt = 0;
    if(l == 0)
        cnt += (r-l)*a;
    else
        cnt += (r-l)*a + min(n-l,r-n)*a;
    /*
    for(int i=l;i<=r;i++){
        cnt += ((str[i]=='h')?0:b) + 1;
    }
    */
    return cnt + pre[r+1] - pre[l];
    //return cnt;
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&a,&b,&T)){
        scanf(" %s",str);
        for(int i = 0;i < n;i++)str[i+n]=str[i];
        pre[0] = 0;
        int tn = n<<1;
        for(int i = 1;i <= tn;i++)pre[i] = pre[i-1] + (str[i-1]=='h'?0:b) + 1;
        int num = 0;
        for(int i = 0;i <= n;i++){
            int l = i , r = i + n - 1 ;
            if(l != 0) l = n;
            while(l <= r){
                int mid = (l + r) >> 1;
                LL val = Calc(i,mid);
                if(val <= (LL)T){
                    num = max(num,mid-i+1);
                    //printf(":%d %d %.*s\n",i,mid,mid-i+1,str+i);
                    l = mid + 1;
                }
                else r = mid -1;
            }
        }
        printf("%d\n",num);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值