D. Tokitsukaze, CSL and Stone Game
题意:有n堆石头,每人每次只能去一颗石子,若轮到当前人没任何一堆石子可以取或当前人取到后剩下有俩堆石子个数相同则当前人输;
给定石子序列。
分析:1、若有类似“2 3 3 ”则后手胜,因为有这个序列就必须在这个序列中去石子(因为如果在这个序列以外取子,则会导致输的后者情况),但在这个序列中取不到可解情况,所以该状态为必败态;
2、若序列中有俩对相同的石子,则后手胜;
3、除1、2情况外就把利用sum+起来,每个加就+a[i]-(i+1) 为了把他提到前面他不能再动的最优状态(因为俩者都采取最优策略!!!)
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll a[100005]; int main(){ int n; ll sum=0; cin>>n; for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i]; sort(a+1,a+1+n); int countt=0; for(int i=1;i<n;i++){ if(a[i]==a[i+1]){ if(a[i]==0||(i>1&&a[i-1]+1==a[i])||++countt>1){ return puts("cslnb"),0; } } } sum-=n*(n-1)/2; if(sum%2==0) puts("cslnb"); else puts("sjfnb"); return 0; }
F. Tokitsukaze and Strange Rectangle
分析:1、对于每一个点来说,他对问题的贡献为“对于某个点(图中的红点),包含这个点的区间个数是(a区间点个数+1)*(b区间点个数+1)”因为涉及区间个数,所以考虑用树状数组求;
2、问题给的x和y1e9,所以要离散化处理一下;
3、离散化后的坐标是紧挨在一起的!!!!
4、对于分析第1步的a区间即为不包含当前点的左区间的点的个数,b区间则为不包含当前点的右区间(为了避免重复计算,这个区间的右端点应为当前点的下一点-1);
5、至于分析第1步为啥都要+1,是为了: 点的个数加1个位置可以作为区间端点的取值;
#include<bits/stdc++.h> using namespace std; const int M=2e5+5; typedef long long ll; int bit[M],x[M],y[M],vis[M]; vector<int>tx,ty,zuobiao[M]; void add(int xx){ while(xx<M) bit[xx]++,xx+=xx&-xx; } int sum(int xx){ int ans=0; while(xx) ans+=bit[xx],xx-=xx&-xx; return ans; } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&x[i],&y[i]); tx.push_back(x[i]); ty.push_back(y[i]); } sort(tx.begin(),tx.end()); sort(ty.begin(),ty.end()); for(int i=1;i<=n;i++){ x[i]=lower_bound(tx.begin(),tx.end(),x[i])-tx.begin()+1; y[i]=lower_bound(ty.begin(),ty.end(),y[i])-ty.begin()+1; zuobiao[y[i]].push_back(x[i]); } ll ans=0; for(int i=M-1;i>=1;i--){ if(zuobiao[i].size()==0) continue; sort(zuobiao[i].begin(),zuobiao[i].end()); for(int j=0;j<zuobiao[i].size();j++){ int xx=zuobiao[i][j]; if(!vis[xx]) add(xx),vis[xx]=1; int l=sum(xx-1); int r; if(j+1==zuobiao[i].size()) r=sum(M-1)-sum(xx); else r=sum(zuobiao[i][j+1]-1)-sum(xx); ans+=(l+1)*1ll*(r+1); } } printf("%I64d ",ans); return 0; }