A-Cards for Friends
题解
按照题意直接模拟就行,答案就是能 (被w乘除的最大的2的n次幂) 乘以 (被h乘除的最大的2的n次幂)。
判断是否大于等于n就行了。
简单做法:巧妙利用二进制运算&处理,答案就是( w&(-w) )*( h&(-h) ),这个运算在树状数组中用的比较多。
麻烦做法:直接根据题意模拟即可。
代码
做法一
if(1ll*(w&(-w))*(h&(-h))>=n) puts("YES"); else puts("NO");
做法二
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 1e5+7; int a[N]; void solve(){ int w=read(),h=read(); int n=read(); ll cnt1=1,cnt2=1; ll cur=1; while(w%2==0){ w/=2,cnt1+=cur,cur*=2; if(cnt1>=n){ puts("YES"); return ; } } cur=1; while(h%2==0){ h/=2,cnt2+=cur,cur*=2; if(cnt1>=n){ puts("YES"); return ; } } if(cnt1*cnt2>=n) puts("YES"); else puts("NO"); } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); //debug = 1; #endif //time_t beg, end; //if(debug) beg = clock(); int T=read(); while(T--) solve(); /* if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } */ return 0; }
B-Fair Division
题解
题目给的范围很小,所以我们可以直接枚举1的个数和2的个数,然后判断存在当前组成的数是否和剩下的数相等即可。
也可以找规律
实际上,如果总和是偶数,并且至少有两个糖果的重量为1,那么答案始终是“Yes”(我们可以收集重量为2的糖果使得总重量尽可能接近一半的重量,然后添加重量为1的糖果)。
如果没有权重为1的糖果,则需要检查n是否为偶数(由于所有糖果的权重相同,因此只需要将它们分成两半即可)。
代码
做法一——枚举
rp(i,0,cnt1){ rp(j,0,cnt2){ if(i+j*2==cnt1-i+(cnt2-j)*2){ puts("YES"); return; } } } puts("NO");
做法二——规律
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int a[107]; void solve(){ int n=read(); rp(i,1,n) a[i]=read(); int cnt1=0,cnt2=0; rp(i,1,n){ if(a[i]==1) cnt1++; else cnt2++; } int sum=cnt1+cnt2*2; if((sum%2==0&&cnt1>=2)||(n%2==0&&cnt1==0)) puts("YES"); else puts("NO"); } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); //debug = 1; #endif //time_t beg, end; //if(debug) beg = clock(); int T=read(); while(T--) solve(); /* if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } */ return 0; }
C-Long Jumps
题解
这个题有两个做法:dp记忆化或者逆序维护。
不难发现每个下标在第一次确定值后,在以后的其他下标进行操作时就不变了。
因此最直接的做法就来了,根据题意直接模拟就行,但是注意要记忆化一下(因为上面的那条性质),这样才不会超时。
当然也可以直接逆序维护,这个比较好写。
代码
做法一——逆序维护
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 2e6+7; int a[N]; ll sum[N]; int vis[N]; int n; void solve(){ n=read(); rp(i,1,n) sum[i]=0; rp(i,1,n) a[i]=read(); RP(i,n,1){ if(i+a[i]>n) sum[i]=a[i]; else sum[i]=sum[i+a[i]]+a[i]; } printf("%lld\n",*max_element(sum+1,sum+1+n)); } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); //debug = 1; #endif //time_t beg, end; //if(debug) beg = clock(); int T=read(); while(T--) solve(); /* if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } */ return 0; }
做法二——记忆化搜索
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 2e5+7; int a[N]; ll sum[N]; int n; int dfs(int index){ if(index>n) return 0; if(sum[index]!=-1) return sum[index]; // outval(index); return sum[index]=a[index]+dfs(index+a[index]); } void solve(){ n=read(); rp(i,1,n) sum[i]=-1; rp(i,1,n) a[i]=read(); rp(i,1,n) if(sum[i]==-1) dfs(i); ll ans=0;rp(i,1,n) ans=max(ans,sum[i]); cout<<ans<<endl; } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); debug = 1; #endif time_t beg, end; if(debug) beg = clock(); int T=read(); while(T--) solve(); if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } return 0; }
D-Even-Odd Game
题解
根据题意不难想到当轮到Alice时,肯定选择对他获益最大的,这里的获益不仅指Alice可以拿到的分数,也可以这是对Bob造成的伤害(即需要使得Bob获益最小),Bob的情况同理。
因此模拟整个游戏过程,当轮到某人时,某人选择对自己获益最大的操作即可,与此同时维护Alice和Bob的和就行了。
最后判断Alice和Bob能够取到的和的大小即可。
代码
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 2e5+7; int a[N]; void solve(){ int n=read(); vector<int> v1,v2; ll sum=0; rp(i,1,n){ a[i]=read(); if(a[i]&1) v2.p_b(a[i]); else v1.p_b(a[i]); sum+=a[i]; } sort(v1.begin(),v1.end()); sort(v2.begin(),v2.end()); int f=1; int cnt=n; ll sum1=0,sum2=0; while(cnt>0){ if(f){ if(v2.size()>0&&v1.size()>0){ if(v2[v2.size()-1]>v1[v1.size()-1]) v2.pop_back(); else { sum1+=v1[v1.size()-1]; v1.pop_back(); } } else if(v1.size()>0) { sum1+=v1[v1.size()-1]; v1.pop_back(); } else v2.pop_back(); } else{ if(v2.size()>0&&v1.size()>0){ if(v2[v2.size()-1]<v1[v1.size()-1]) v1.pop_back(); else { sum2+=v2[v2.size()-1]; v2.pop_back(); } } else if(v2.size()>0) { sum2+=v2[v2.size()-1]; v2.pop_back(); } else v1.pop_back(); } f^=1; cnt--; } // cout<<sum1<<" "<<sum2<<endl; if(sum1>sum2) puts("Alice"); else if(sum1==sum2) puts("Tie"); else puts("Bob"); } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); //debug = 1; #endif //time_t beg, end; //if(debug) beg = clock(); int T=read(); while(T--) solve(); /* if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } */ return 0; }
E-Correct Placement
题解
大致理解题意后以为是一道二维偏序的题,仔细想了想没有那么麻烦,只需要维护个线段树(或者维护前缀最小值下标数组)。
首先把每个人按照h进行排序,同时线段树维护区间w最小值和最小值下标。
这样就能先二分筛出来一批(h比当前h(或者w)小的人),
然后每次操作时,用线段树查询这批人里面的最小的w,判断这个最小的w是否比当前w(或者h)小,如果小的话,则表示这批人里面w最小的那个人可以站在现在这个人前面,记录下标即可。
代码
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define dg if(debug) #define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n"; using namespace std; int debug = 0; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 2e5+7; struct node{ int w,h,id; bool operator < (const struct node b)const{ return (*this).h<b.h; } }p[N]; int ans1[N],ans2[N]; ll a[N]; struct edge { int id; int left,right; ll min; }num[N*4]; //建树 pair<int,ll> buildmin(int left,int right,int cnt) { int mid; num[cnt].left=left; num[cnt].right=right; if(left==right) { num[cnt].id=left; num[cnt].min=p[left].w; return make_pair(left,p[left].w); } mid=(left+right)>>1; pair<int,ll> r1=buildmin(left,mid,cnt*2); pair<int,ll> r2=buildmin(mid+1,right,cnt*2+1); if(r1.second<r2.second) { num[cnt].id=r1.first; num[cnt].min=r1.second; return r1; } else { num[cnt].id=r2.first; num[cnt].min=r2.second; return r2; } } //返回pair类型,first为下标,second为最小值 pair<int,ll> querymin(int left,int right,int cnt) { int mid; if(left==num[cnt].left&&right==num[cnt].right) return make_pair(num[cnt].id,num[cnt].min); mid=(num[cnt].left+num[cnt].right)>>1; if(right<=mid) return querymin(left,right,cnt*2); else if(left>mid) return querymin(left,right,cnt*2+1); else { pair<int,ll> r1=querymin(left,mid,cnt*2); pair<int,ll> r2=querymin(mid+1,right,cnt*2+1); return r1.second<r2.second?r1:r2; } } void solve(){ int n=read(); rp(i,1,n) p[i].h=read(),p[i].w=read(),p[i].id=i; rp(i,1,n) ans1[i]=ans2[i]=-1; sort(p+1,p+1+n); buildmin(1,n,1); rp(i,1,n){ int id=lower_bound(p+1,p+1+n,node{0,p[i].h,0})-p; id--; if(id==0) continue; ll val=querymin(1,id,1).second; int Id=querymin(1,id,1).first; if(val<p[i].w) ans2[p[i].id]=p[Id].id; } rp(i,1,n){ int id=lower_bound(p+1,p+1+n,node{0,p[i].w,0})-p; id--; if(id==0) continue; ll val=querymin(1,id,1).second; int Id=querymin(1,id,1).first; if(val<p[i].h) ans2[p[i].id]=p[Id].id; } rp(i,1,n){ if(ans1[i]==-1&&ans2[i]==-1) printf("-1"); else if(ans1[i]!=-1) printf("%d",ans1[i]); else printf("%d",ans2[i]); printf("%s",i==n?"\n":" "); } } int main(){ //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); //debug = 1; #endif //time_t beg, end; //if(debug) beg = clock(); int T=read(); while(T--) solve(); /* if(debug) { end = clock(); printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC); } */ return 0; }
Codeforces Round #693 (Div. 3)ABCDE——解题报告
最新推荐文章于 2021-05-24 08:02:20 发布