《Alive》
A. Joysticks
有两个游戏柄和一个充电器,初始时两个游戏柄的电量分别为a
%和b
%,某个游戏柄如果连接充电器的话每分钟可以提升1
%的电量,如果不连接充电器每分钟掉2
%的电量,如果某游戏柄的电量<=0就不能玩。问最多能玩多久?
1≤a1,a2≤100
输入:
1 1
输出:
0
输入:
3 5
输出:
6
输入:
4 4
输出:
5
.
.
.
.
.
.
.
.
.
范围小。。枚举。。策略是贪心。。哪个电量少就给哪个充电。。
#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\n",ans); } return 0; }
|
扩展
如果数据量大,就是不用枚举或者单位为毫秒或者微秒。。1≤a,b≤1010 怎么求?
B. Beautiful Paintings
给一个长度为n(1≤n≤1000)的数组,对于每个数字1≤ai≤1000,把这个数组的顺序重新组合后求最多有多少对ai−1<ai
1≤ai≤1000
输入:
5
20 30 10 50 40
输出:
4
输入:
4
200 100 100 200
输出:
2
.
.
.
.
.
.
.
.
.
.
范围小。。哈系,枚举。。
#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个点( 1≤n≤200000 ),问有多少对点(i,j)( i<j )可以使得以下成立
∣xi−xj∣+∣yi−yj∣=2(xi−xj)2+(yi−yj)2
∣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
.
.
.
.
.
.
.
.
.
.
.
.
计算某行的组合+某列的组合-自己和自己的组合
#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]){ 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]){ ans += 1LL*(tmp[pos]-1)*tmp[pos]/2; tmp[pos]=0; } } sort(cs,cs+n,cmp); int cnt=1; int tx=cs[0].x,ty=cs[0].y; for(int i=1;i<n;i++){ if(tx==cs[i].x&&ty==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; }
|
D.
有n张图片在手机里(1≤n≤5∗105),看一张图片需要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
.
.
.
.
.
.
.
.
.
.
.
只有四种情况:
- 从第一张一直往右边看
- 从第一张一直往左边看
- 从第一张先往左边看,再往右边看
- 从第一张先往右边看,再往左边看
只需要固定一个点,然后二分求就可以了复杂度O(nlogn)。。注意这里如果不预处理,复杂度会退化成O(n2logn)
#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;
return cnt + pre[r+1] - pre[l]; } 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); l = mid + 1; } else r = mid -1; } } printf("%d\n",num); } return 0; }
|