《Alive》  

A. Joysticks

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

输入:  
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,b10101 \leq a , b \leq 10^{10} 怎么求?

B. Beautiful Paintings

给一个长度为n(1n10001 \leq n \leq 1000)的数组,对于每个数字1ai10001 \leq a_i \leq 1000,把这个数组的顺序重新组合后求最多有多少对ai1<aia_{i-1} \lt a_{i}

1ai10001 \leq a_i \leq 1000

输入:  
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个点( 1n2000001 \leq n \leq 200 000 ),问有多少对点(i,j)( i<ji \lt j )可以使得以下成立

xixj+yiyj=(xixj)2+(yiyj)22|x_i - x_j| + |y_i - y_j| = \sqrt[2]{(x_i - x_j)^2 + (y_i - y_j)^2}
xi,yi109|x_i|,|y_i| \leq 10^9

输入:  
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张图片在手机里(1n51051 \leq n \leq 5*10^5),看一张图片需要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. 从第一张一直往右边看
  2. 从第一张一直往左边看
  3. 从第一张先往左边看,再往右边看
  4. 从第一张先往右边看,再往左边看
    只需要固定一个点,然后二分求就可以了复杂度O(nlogn)O(nlogn)。。注意这里如果不预处理,复杂度会退化成O(n2logn)O(n^2logn)
//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;
}