题意:n的士兵,每个士兵有一些生命值,有q次询问,每次询问从前向后造成ki点贯穿伤害(生命值归零的士兵死去,后续士兵承受溢出伤害),问每次询问有几个士兵还活着。当所有士兵死去时,不继续造成溢出伤害并且所有士兵复活。
思路:二分搜索,对士兵生命值求前缀和,每次询问造成的伤害累计,记为s,用upper_bound来寻找前缀和中大于s的第一个人的位置i,n-i就是剩下的人数,如果剩下的人数为0(死完了),就全部复活,s清0。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int MAX_N = 200000 + 8; 5 ll x[MAX_N]; 6 ll sum[MAX_N]; 7 int main() 8 { 9 int i,n,q; 10 cin >> n >> q; 11 12 memset(sum,0x3f,sizeof(sum)); 13 for(i=0;i<n;i++){ 14 cin >> x[i]; 15 if(i) 16 sum[i]=sum[i-1]+x[i]; 17 else 18 sum[i]=x[i]; 19 } 20 ll s=0,tmp; 21 for(i=0;i<q;i++){ 22 cin >> tmp; 23 s+=tmp; 24 int index=upper_bound(sum,sum+MAX_N,s)-sum; 25 if(n-index<=0) 26 { 27 s=0; 28 index=0; 29 } 30 cout << n-index << "\n"; 31 } 32 return 0; 33 }
Codeforces Round #476 (Div. 2)
http://codeforces.com/contest/965/problem/C
D<=1000,因此可以简单枚举,每次最大一定是n/((i-1)*k+1) * i,但是有很多情况需要特判排除。
题解,https://www.cnblogs.com/AWCXV/p/8949119.html
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 6 int main() 7 { 8 ios_base::sync_with_stdio(false); 9 cin.tie(0); 10 ll n,k,M,D; 11 cin >> n >> k >> M >> D; 12 ll ans=M; 13 for(ll i=2;i<=D;i++) 14 { 15 ll x=n/((i-1)*k+1); 16 17 if(x==0)break; 18 if(x>M)x=M; 19 if ((n/(k*x)+((n%(k*x)>=x?1:0)))!=i) continue; 20 ans=max(ans, x*i); 21 } 22 cout << ans << "\n"; 23 24 return 0; 25 }
2018/5/17
http://codeforces.com/contest/984/problem/C
题意:给出p,q,b,求b进制下p/q是否为无穷小数。
思路:先用gcd将p/q化为真分数,再对于q和b:由于p和q互质,之后的过程就与p无关了。
由于是b进制,每进一位就相当于原小数*b,那么这个过程中就相当于q/gcd(q,b)。持续到q和gcd(q,b)其中一个为1即可。
一开始直接用快速幂……超时,%lld CF不能用CE。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 6 ll gcd(ll x,ll y){ 7 return y==0?x:gcd(y,x%y); 8 } 9 10 11 int main() 12 { 13 ios::sync_with_stdio(false); 14 cin.tie(0); 15 ll p,q,b; 16 int n; 17 cin >> n; 18 while(n--){ 19 cin >> p >> q >>b; 20 ll x=p/gcd(p,q); 21 ll y=q/gcd(p,q); 22 ll cheek=gcd(y,b); 23 while(y!=1&&cheek!=1){ 24 while(y%cheek==0)y/=cheek; 25 cheek=gcd(b,y); 26 } 27 if(y==1) 28 cout << "Finite\n"; 29 else 30 cout << "Infinite\n"; 31 } 32 }
2018/5/22
http://codeforces.com/contest/982
B
【题意】:
就是说有一辆公交车,有n排;
接下来n个数据代表n排的权值(每排只能坐2个人);
然后接下来又2*n的数据
代表要坐入这辆公交车的人的类型。
1代表外向型,0代表内向型。
外向型:优先选择旁边有人的且权值最大的位置,如果没有的话,选择权值最大的位置。
内向型:优先选择没人的位置且权值最小的位置。
【思路】:
首先定义座位的属性:
状态:0代表旁边没人,1代表旁边有人。
第几排
权值
维护两个优先队列
优先队列0,用于维护旁边没人的座位,权值最小的排在最前面。
优先队列1,用于维护旁边有人的座位,权值最大的排在最前面。
一开始座位都没人,都存入队列0.
每次操作,从相应队列找最前面的位置,若队列0中找到座位,则将座位的状态改变存入队列1.
之后删除相应队列中的该座位。
输出即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 struct node{ 6 int state; 7 int row; 8 int pow; 9 node(int s,int r,int p):state(s),row(r),pow(p){}; 10 node(){} 11 }; 12 13 struct rule0{ 14 bool operator()(const node &a,const node &b){ 15 return a.pow<b.pow||a.pow==b.pow&&a.row<b.row; 16 } 17 }; 18 19 struct rule1{ 20 bool operator()(const node &a,const node &b){ 21 return a.pow>b.pow||a.pow==b.pow&&a.row<b.row; 22 } 23 }; 24 25 int main(){ 26 set<node,rule1> st1; 27 set<node,rule0> st0; 28 set<node,rule0>::iterator it0; 29 set<node,rule1>::iterator it1; 30 31 int n; 32 cin >> n; 33 int pow; 34 for(int i=0;i<n;i++){ 35 cin >> pow; 36 node tmp(0,i+1,pow); 37 st0.insert(tmp); 38 } 39 string people; 40 cin >> people; 41 for(int i=0;people[i];i++){ 42 if(people[i]=='0'){ 43 it0=st0.begin(); 44 if(it0!=st0.end()){ 45 node tmp=*it0; 46 st0.erase(it0); 47 tmp.state++; 48 st1.insert(tmp); 49 printf("%d%c",tmp.row,i==2*n-1?'\n':' '); 50 continue; 51 } 52 else{ 53 it1=st1.begin(); 54 node tmp=*it1; 55 st1.erase(it1); 56 printf("%d%c",tmp.row,i==2*n-1?'\n':' '); 57 continue; 58 } 59 60 } 61 else { 62 it1=st1.begin(); 63 if(it1==st1.end()){ 64 it0=st0.begin(); 65 node tmp=*it0; 66 st0.erase(it0); 67 tmp.state++; 68 st1.insert(tmp); 69 printf("%d%c",tmp.row,i==2*n-1?'\n':' '); 70 continue; 71 } 72 else{ 73 node tmp=*it1; 74 st1.erase(it1); 75 printf("%d%c",tmp.row,i==2*n-1?'\n':' '); 76 continue; 77 } 78 } 79 } 80 }
C
题意:https://www.cnblogs.com/kickit/p/9054233.html
给出一棵树,问最多去掉多少条边之后,剩下的连通分量的size都是偶数。
思路:
如果本来就是奇数个点,那么无论去掉多少条边都不可能成立的。
如果是偶数个点,就进行一次dfs,假设一个点的父亲是u,儿子是v,那么可以去掉(u,v)的条件就是v及其子树有偶数个点,任何一条这样的边都是可以去掉的。
所以一边dfs,一边统计答案就可以了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n; 5 vector<int> v[100010]; 6 int ret; 7 int dfs(int u,int f){ 8 int ans=1; 9 for(int i=0;i<v[u].size();i++){ 10 if(v[u][i]!=f){ 11 int tmp=dfs(v[u][i],u); 12 if(tmp%2==0)ret++; 13 ans+=tmp; 14 } 15 } 16 return ans; 17 } 18 19 int main(){ 20 cin >> n; 21 if(n&1){ 22 cout << -1 <<endl; 23 return 0; 24 } 25 26 int x,y; 27 int start=-1; 28 for(int i=1;i<n;i++){ 29 cin >>x >>y; 30 v[x].push_back(y); 31 v[y].push_back(x); 32 } 33 dfs(1,-1); 34 cout << ret <<endl; 35 }
479 C
阴险的陷阱题……
题意:
给一些数,范围从1到1e9,问是否存在一个数,使得正好有k个数小于等于这个数
思路:
很容易想到排序,前k个数一定是选入的,只要判断第k+1个数是否等于第k个数即可。
然而……WA了
问题在于k可以取0.
范围是从1开始的,所以还要判断这种情况下最小的数是否大于1,以上。
codeforces.com/contest/977
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 int main(){ 6 int x[200010]; 7 int n,k; 8 while(cin >> n >> k){ 9 memset(x,0x3f,sizeof(x)); 10 for(int i=0;i<n;i++){ 11 cin >> x[i]; 12 } 13 sort(x,x+n); 14 if(k==0){ 15 if(x[0]>1) 16 printf("1\n"); 17 else 18 printf("-1\n"); 19 continue; 20 } 21 else if(x[k]!=x[k-1]) 22 printf("%d\n",x[k-1]); 23 else 24 printf("-1\n"); 25 26 } 27 }
Educational Codeforces Round 42
C. Make a Square
http://codeforces.com/contest/962/problem/C
题意:给一个无前导零的数,你可以删除任意多的数字,使得它成为一个无前导零的平方数……吗?若可以,输出最少操作数,若不可以,输出-1.
思路:
混乱……
开玩笑的,今天状态太差了,这么一道破水题卡了我一个小时,我还看题解了……
总之,题目很简单,暴力枚举,数据范围2e9,枚举所有可能情况最多也就1024种情况,每种情况判断是否无前导零、是否为平方数(开根号平方等于本身)即可。
一开始zz想用ac自动机被卡、情况0未考虑被卡、前导零未考虑被卡……
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <string> 5 #include <iostream> 6 #include <math.h> 7 using namespace std; 8 9 int main() 10 { 11 int i,j,tmp; 12 string t; 13 cin >> t; 14 int flag=0,ans=0; 15 for(i=1;i<(1<<t.size());i++){ 16 tmp=i; 17 int s=0; 18 j=0; 19 int num=0; 20 while(tmp>0){ 21 if( !(!s&&t[j]=='0') && (tmp&1) ){ 22 s=s*10+t[j]-'0'; 23 num++; 24 } 25 j++; 26 tmp>>=1; 27 } 28 if(s&&(int)sqrt(s)*(int)sqrt(s)==s ){ 29 ans=max(ans,num); 30 flag=1; 31 } 32 } 33 if(!flag){ 34 printf("-1\n"); 35 } 36 else 37 printf("%d\n",t.size()-ans); 38 return 0; 39 }
5.24
http://codeforces.com/contest/985
越写越觉得自己是zz……
1.水题暴力即可,没考虑排序……
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 int abs(int x){ 5 return x > 0 ? x : -x; 6 } 7 8 int main() 9 { 10 int n; 11 int x[110]; 12 cin >> n ; 13 for(int i=0;2*i<n;i++){ 14 cin >> x[i]; 15 } 16 sort(x,x+n/2); 17 int a=0,b=0; 18 for(int i=0;2*i<n;i++){ 19 a+=abs(2*i+2-x[i]); 20 } 21 for(int i=0;2*i<n;i++){ 22 b+=abs(2*i+1-x[i]); 23 } 24 printf("%d\n",min(a,b)); 25 return 0; 26 }
2.水题
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 int x[2010]={0}; 6 string a[2010]; 7 int main() 8 { 9 int n,m,flag,yes=0; 10 cin >> n >> m; 11 for(int i=0;i<n;i++){ 12 cin >> a[i]; 13 for(int j=0;a[i][j];j++){ 14 if(a[i][j]=='1') 15 x[j]++; 16 } 17 } 18 for(int i=0;i<n;i++){ 19 flag=1; 20 for(int j=0;a[i][j];j++){ 21 if(a[i][j]=='1'&&x[j]<2){ 22 flag=0; 23 } 24 } 25 if(flag){ 26 yes=1; 27 printf("YES\n"); 28 break; 29 } 30 } 31 if(!yes){ 32 printf("NO\n"); 33 } 34 return 0; 35 }
3.贪心
确定能选的范围,之后每次选能选到的最大的。
爆int,用long long
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 ll x[100010]; 6 int main() 7 { 8 int n,k,l; 9 cin >> n >> k >> l; 10 for(int i=0;i<n*k;i++){ 11 cin >> x[i]; 12 } 13 sort(x,x+n*k); 14 int index=upper_bound(x,x+n*k,x[0]+l)-x; 15 // cout << index <<endl; 16 if(index<n){ 17 printf("0\n"); 18 return 0; 19 } 20 ll sum=0; 21 // for(int i=0;i<n*k;i++) 22 // printf("%d\t",x[i]); 23 24 for(int i=0;n&&i<index;){ 25 sum+=x[i]; 26 i+=min(k,max(index-i-n+1,1)); 27 n--; 28 // printf("index-i-n+1:%d\n",index-i-n+1); 29 // printf("i:%d\n",i); 30 } 31 cout << sum << endl; 32 return 0; 33 }
5.25
1.水题,注意n==0的情况即可
1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 long long n; 8 cin >> n; 9 if(!n){ 10 cout << 0 << endl; 11 return 0; 12 } 13 n++; 14 15 if(n%2==0) 16 cout <<n/2 <<endl; 17 else 18 cout << n << endl; 19 return 0; 20 }
2.贪心,注意特殊情况,全部相同字符情况n==1时减少一位
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 int main() 6 { 7 string a[3]; 8 int num; 9 cin >> num >> a[0] >> a[1] >> a[2]; 10 int ch[3][300]={0}; 11 for(int j=0;j<3;j++){ 12 13 for(int i=0;a[j][i];i++){ 14 ch[j][ a[j][i] ]++; 15 ch[j][0]=max(ch[j][0],ch[j][a[j][i]]); 16 } 17 if(num==1&&ch[j][0]==(int)a[j].size()){ 18 ch[j][0]--; 19 continue; 20 } 21 ch[j][0]=min(ch[j][0]+num,(int)a[j].size()); 22 23 } 24 int maxn=max(max(ch[0][0],ch[1][0]),ch[2][0]); 25 if(maxn==ch[0][0]&&maxn==ch[1][0]|| 26 maxn==ch[0][0]&&maxn==ch[2][0]|| 27 maxn==ch[2][0]&&maxn==ch[1][0]) 28 cout << "Draw\n"; 29 else if(maxn==ch[0][0]) 30 cout << "Kuro\n"; 31 else if(maxn==ch[1][0]) 32 cout << "Shiro\n"; 33 else if(maxn==ch[2][0]) 34 cout << "Katie\n"; 35 36 return 0; 37 }