A
题目大意:给你总的比赛场次数,再给你目前的比分,问你这场比赛的结果是不是已经出来了。
也就是有一个人的分数达到n/2+1就代表结束了
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,t,a[N];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cout<<fixed<<setprecision(2);
cin>>n>>t>>m;
if(t>=(n+1)/2||m>=(n+1)/2)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
B
题目大意:给你n个字符串,让你按列的顺序逆序输出,在同一列长度下部分字符串是没有的,就用星号*来表示,并且删除后缀的星号。
模拟。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,t;
string a[N];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cout<<fixed<<setprecision(2);
cin>>n;
int M=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(M<a[i].size())M=a[i].size();
}
string ans[N];
for(int i=0;i<M;i++)
{
for(int j=n;j>=1;j--)
{
if(i<a[j].size())ans[i]+=a[j][i];
else ans[i]+='*';
}
}
for(int i=0;i<M;i++)
{
while(ans[i].size()&&ans[i][ans[i].size()-1]=='*')ans[i].erase(ans[i].size()-1);
}
for(int i=0;i<M;i++)cout<<ans[i]<<endl;
}
C
题目大意:1 x代表加入x这个数,2 x代表删除这个数,3即输出现在还有多少种数字。
一个set用来标记数字的种数,map用来记录数字的数量,输出就输出set的size。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,t;
map<int,int>p;
set<int>q;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cout<<fixed<<setprecision(2);
cin>>t;
while(t--)
{
int x,y;
cin>>x;
if(x==1)
{
cin>>y;
p[y]++;
if(p[y]==1)
{
q.insert(y);
}
}
else if(x==2)
{
cin>>y;
p[y]--;
if(p[y]==0)
{
q.erase(q.find(y));
}
}
else if(x==3)
{
cout<<q.size()<<endl;
}
}
}
D
题目大意:三维前缀和。
也就是三维前缀和。
a[i][j][p]+=a[i-1][j][p]+a[i][j-1][p]+a[i][j][p-1]-a[i-1][j-1][p]-a[i-1][j][p-1]-a[i][j-1][p-1]+a[i-1][j-1][p-1];
以及查询
ans=a[rx][ry][rz]-a[lx-1][ry][rz]-a[rx][ly-1][rz]-a[rx][ry][lz-1]+a[lx-1][ly-1][rz]+a[lx-1][ry][lz-1]+a[rx][ly-1][lz-1]-a[lx-1][ly-1][lz-1];
#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int n,m,t,a[N][N][N],q;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cout<<fixed<<setprecision(2);
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=1;p<=n;p++)cin>>a[i][j][p];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=1;p<=n;p++)
{
a[i][j][p]+=a[i-1][j][p]+a[i][j-1][p]+a[i][j][p-1]-a[i-1][j-1][p]-a[i-1][j][p-1]-a[i][j-1][p-1]+a[i-1][j-1][p-1];
}
}
}
cin>>q;
while(q--)
{
int lx,rx,ly,ry,lz,rz;
cin>>lx>>rx>>ly>>ry>>lz>>rz;
int ans=a[rx][ry][rz]-a[lx-1][ry][rz]-a[rx][ly-1][rz]-a[rx][ry][lz-1];
ans=ans+a[lx-1][ly-1][rz]+a[lx-1][ry][lz-1]+a[rx][ly-1][lz-1]-a[lx-1][ly-1][lz-1];
cout<<ans<<endl;
}
}
E
题目大意:给你n个二维点,还有一个D,要求有一个点与这n个点的曼哈顿距离必须小于等于D。问一共有多少个这样的点。
优先降维,将二维分成x和y这两个一维,那么在x轴符合条件的x坐标,找到对应有多少y轴坐标数量符合条件,那么就是总的可能性。
可以发现,在x这个点上时,他的差值和为sum。那么在x+1这个点上时,左边的点数量是l,右边的点数量是r,那么x+1上的差值和就是sum-l+r。
如果放在函数上就是一个单峰函数,也可能是个平底锅。这同样适用于y坐标,所以我们只要枚举所有的x坐标,然后找到可行的y坐标范围就可以了。
内存分配了一个g,那就瞎预处理,内存反正够用,把每个y坐标的曼哈顿距离全部处理出来,并以峰值点为中心点进行分割,分成两部分,排个序让这两部分都是递增序列,这样我们查找的时候直接upper_bound查可能得y值就可以直接查到数量了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=6e6+10;
int n,m,t,x[N],y[N],a[N],b[N],sumx,sumy,d,ans,Miny;
vector<int>ly,ry;
void Init()
{
int t=1;
for(int i=0;i<=6e6;i++)
{
while(t<=n&&x[t]<i)t++;
if(i!=0)
{
sumx+=t-1;
sumx-=n-t+1;
}
a[i]=sumx;
}
t=1;
for(int i=0;i<=6e6;i++)
{
while(t<=n&&y[t]<i)t++;
if(i!=0)
{
sumy+=t-1;
sumy-=n-t+1;
}
b[i]=sumy;
if(b[Miny]>sumy)Miny=i;
}
for(int i=0;i<=Miny;i++)ly.push_back(b[i]);
for(int i=Miny+1;i<=6e6;i++)ry.push_back(b[i]);
sort(ly.begin(),ly.end());
sort(ry.begin(),ry.end());
}
int sanfen(int x)
{
if(d-a[x]<0)return 0;
int p=d-a[x];
int l=0;
int r=0;
if(upper_bound(ly.begin(),ly.end(),p)!=ly.end())
{
l=upper_bound(ly.begin(),ly.end(),p)-ly.begin();
}
if(upper_bound(ry.begin(),ry.end(),p)!=ry.end())
{
r=upper_bound(ry.begin(),ry.end(),p)-ry.begin();
}
// cout<<l+r<<" "<<p<<endl;
return r+l;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// cout<<fixed<<setprecision(2);
cin>>n>>d;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i],x[i]+=3e6,y[i]+=3e6,sumx+=x[i],sumy+=y[i];
sort(x+1,x+1+n);
sort(y+1,y+1+n);
Init();
// cout<<a[2000000]<<" "<<b[2000000]<<endl;
for(int i=0;i<=6e6;i++)
{
ans+=sanfen(i);
}
cout<<ans<<endl;
}
因为有负坐标,所以我们就把所有坐标加3e6,那么题目的坐标就会在2e6到3e6之间,可行的x坐标就在1e6到4e6之间。但是这么区划范围交上去会wa四个,所以我就扩到0到6e6之间了。赛时做出来wa了我还以为方法错了,结果赛后查别人代码的时候发现怎么8e6都开出来了,我就回去改了一下就过了,绝望了直接。
上一场E题思路直接想歪了,还以为线段树优化呢,结果是异或前缀和的性质,就不想写了。