SMU Spring 2023 Contest Round 1
SMU Spring 2023 Contest Round 1
B - Contest Preparation
思路:特判下m大于n的情况,只有make后才能validate
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>PII; typedef pair<string,int>PSI; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e6; const double eps=1e-6; typedef long long ll; ll t,n,m; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>t; while(t--){ cin>>n>>m; ll s=(2*n+m-1)/m; if(m>n&&n)s=2; cout<<s<<'\n'; } return 0; }
D - Difference
思路:
可以把第k大转换为第几小,二分答案;
check时求f(l,r)可以用st表,手写log,复杂度O(1);st表:https://oi-wiki.org/ds/sparse-table/
check求小于等于mid的f(l,r)个数时,(由于f(l,r-1)<f(l,r)>f(l+1,r);对于特定的l,j递增,f(l,j)也是递增的;同理特定的r也是;)枚举l,求出f(l1,r1)小于等于mid的边界r1,接着继续枚举到l2时,由于f是递增的,f(l2,r1)一定小于等于mid,即r2从上一个r1+1开始遍历,可以用双指针,复杂度O(n);
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>PII; typedef pair<string,int>PSI; const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7; const double eps=1e-6; typedef long long ll; typedef pair<ll,ll>PLL; ll n,k; PLL f[N][20]; ll Log[N]; ll P(int l,int r){ int s=r-l+1; ll ma=max(f[l][Log[s]].first,f[r-(1<<Log[s])+1][Log[s]].first); ll mi=min(f[l][Log[s]].second,f[r-(1<<Log[s])+1][Log[s]].second); return (ma-mi)*1ll*s*1ll; } bool check(ll x){ ll cnt=0; int j=1; for(int i=1;i<=n;++i){ if(i>j)j=i; while(j<=n&&P(i,j)<=x)j++; cnt+=(j-i)*1ll; } return cnt>=k; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>k; k=n*(n+1)/2-k+1; for(int i=1;i<=n;++i)cin>>f[i][0].first,f[i][0].second=f[i][0].first; for(int i=2;i<=n;++i)Log[i]=Log[i/2]+1; for(int i=1;i<=20;++i) for(int j=1;j+(1<<i)-1<=n;++j){ f[j][i].first=max(f[j][i-1].first,f[j+(1<<(i-1))][i-1].first); f[j][i].second=min(f[j][i-1].second,f[j+(1<<(i-1))][i-1].second); } ll ma=max(f[1][Log[n]].first,f[n-(1<<Log[n])+1][Log[n]].first); ll mi=min(f[1][Log[n]].second,f[n-(1<<Log[n])+1][Log[n]].second); ll l=0,r=n*(ma-mi)*1ll; //cout<<ma<<" "<<mi<<'\n'; while(l<r){ ll mid=l+r>>1; if(check(mid))r=mid; else l=mid+1; } cout<<l; return 0; }
K - Triangles
思路:对于只有斜率为1这种直线,可直接用x-y映射出位置(同理斜率为-1时可用x+y映射),求三角形个数:有k个点连续的直线形成的个数为 k *(k+1)/ 2;求出所有连续点的个数即可;
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>PII; typedef pair<string,int>PSI; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e6; const double eps=1e-6; typedef long long ll; int n; int a[505][505]; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n; for(int i=0,x,y;i<n;++i){ cin>>x>>y; a[x][y]=1; } int b=0; for(int i=1;i<=500;++i) { for (int j = 0; j + i <= 500; ++j) { int x = 1 + j, y = i + j, c = 1; if (a[x][y] == 0)continue;//cout<<"*\n"; while (x + 1 <= 500 && y + 1 <= 500 && a[x+1][y+1]==1) {//cout<<x<<' '<<y<<'\n'; a[x][y]=0; x++, y++; c++; }//cout<<x<<' '<<y<<'\n'; a[x][y]=0; b += c*(c+1)/2; } } int bb=0; for(int i=2;i<=500;++i){ for(int j=0;j+i<=500;++j){ int x=i+j,y=1+j,c=1; if(a[x][y]==0)continue;//cout<<"*\n"; while(x+1<=500&&y+1<=500&&a[x+1][y+1]){//cout<<x<<' '<<y<<'\n'; a[x][y]=0; x++,y++; c++; } a[x][y]=0; //cout<<x<<' '<<y<<'\n'; bb+=c*(c+1)/2; } } //cout<<b<<' '<<bb<<'\n'; cout<<(b+bb)*2; return 0; }
M - XOR Almost Everything
思路:两种方法:
1.对所有数操作一次,每次操作异或的数为本身
2.对相邻每两个数分别进行一次操作,两次操作异或的数为第一个数,得到最后一个数为所有数的异或和,其余数为0;再对最后一个数操作,异或的数为最后一个数
最后所有数都等于所有数的异或和p,在对所有数进行方法一,得到所有数为p^p^p.....(n个),判断n的奇偶即可,偶数一定可以,奇数时所有数的异或和为0则可以;
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>PII; typedef pair<string,int>PSI; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e6; const double eps=1e-6; typedef long long ll; int n; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n; ll s=0,x; for(int i=0;i<n;++i){ cin>>x; s^=x; } if(s==0&&n%2==1||n%2==0)cout<<"YES"; else cout<<"NO"; return 0; }