B. clay17与segMilkTrea
- 类型数的统计并没有很巧妙高效的方案,就是朴素地用桶维护。所以可以考虑朴素地求出一轮的方案,再通过数据结构维护快速地过渡到下一轮。
- 线段树的标记一定是具有可加性的
#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long inv[1000005];
int power(int n,int p)
{
if(p==0)
{
return 1;
}
long long tmp=power(n,p/2);
if(p%2==1)
{
return tmp*tmp%mod*n%mod;
}
return tmp*tmp%mod;
}
int n,a[1000005],raw[1000005];
map<int,int>v;
long long s[1000005];
int h[1000005],cur[1000005],nx[1000005];
struct t1
{
int l,r;
long long v;
int bj;
}t[4000005];
void build(int p,int l,int r)
{
t[p].l=l;
t[p].r=r;
t[p].bj=0;
if(l==r)
{
t[p].v=s[l];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].v=(t[p*2].v+t[p*2+1].v)%mod;
}
void spread(int p)
{
if(t[p].bj)
{
t[p*2].bj+=t[p].bj;
t[p*2+1].bj+=t[p].bj;
(t[p*2].v*=inv[t[p].bj])%=mod;
(t[p*2+1].v*=inv[t[p].bj])%=mod;
t[p].bj=0;
}
}
void change(int p,int l,int r)
{
if(l<=t[p].l&&r>=t[p].r)
{
(t[p].v*=inv[1])%=mod;
t[p].bj++;
return;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)
{
change(p*2,l,r);
}
if(r>mid)
{
change(p*2+1,l,r);
}
t[p].v=(t[p*2].v+t[p*2+1].v)%mod;
}
int ask(int p,int l,int r)
{
if(l<=t[p].l&&r>=t[p].r)
{
return t[p].v;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
long long va=0;
if(l<=mid)
{
va+=ask(p*2,l,r);
}
if(r>mid)
{
va+=ask(p*2+1,l,r);
}
return va%mod;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
inv[1]=power(2,998244351);
for(int i=2;i<=1000000;i++)
{
inv[i]=inv[i-1]*inv[1]%mod;
}
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
raw[i]=a[i];
}
sort(raw+1,raw+n+1);
int m=unique(raw+1,raw+n+1)-(raw+1);
for(int i=1;i<=m;i++)
{
v[raw[i]]=i;
}
for(int i=1;i<=n;i++)
{
a[i]=v[a[i]];
nx[cur[a[i]]]=i;
cur[a[i]]=i;
}
long long sum=0;
int cnt=0;
for(int j=1;j<=n;j++)
{
if(!h[a[j]])
{
cnt++;
}
h[a[j]]++;
s[j]=power(2,cnt);
sum=(sum+s[j])%mod;
}
build(1,1,n);
for(int i=1;i<n;i++)
{
h[a[i]]--;
if(h[a[i]]==0)
{
change(1,i+1,n);
}
else
{
if(i+1<=nx[i]-1)
{
change(1,i+1,nx[i]-1);
}
}
sum=(sum+ask(1,i+1,n))%mod;
}
cout<<sum<<endl;
return 0;
}
C. 机器人仓库
- 切比雪夫距离看似很抽象,其实就是允许斜走的路径距离
- \((x,y)\to(\frac{x+y}{2},\frac{x-y}{2}):\)切比雪夫距离转曼哈顿距离
- \((x,y)\to(x+y,x-y):\)曼哈顿距离转切比雪夫距离
- 直接➗2可能存在下取整的问题,可以等到最后统一➗2
- 求到数轴上各点距离和最小的点,其实是中位数问题
#include <bits/stdc++.h>
using namespace std;
struct t1
{
int x,y;
long long t;
}t[100005];
int n;
long long calc(int x,int y)
{
long long res=0;
for(int i=1;i<=n;i++)
{
res=res+max(abs(t[i].x-x),abs(t[i].y-y))*t[i].t;
}
return res;
}
typedef pair<int,int> pii;
vector<pii>a,b;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
double X=0,Y=0;
long long sum=0;
for(int i=1;i<=n;i++)
{
cin>>t[i].x>>t[i].y>>t[i].t;
a.push_back(pii(t[i].x+t[i].y,t[i].t));
b.push_back(pii(t[i].x-t[i].y,t[i].t));
sum+=t[i].t;
}
long long cur=0;
sort(a.begin(),a.end());
for(int i=0;i<a.size();i++)
{
cur+=a[i].second;
if(cur*2>=sum)
{
X=a[i].first/2.0;
break;
}
}
sort(b.begin(),b.end());
cur=0;
for(int i=0;i<b.size();i++)
{
cur+=b[i].second;
if(cur*2>=sum)
{
Y=b[i].first/2.0;
break;
}
}
int x=(int)(X+Y),y=(int)(X-Y);
long long minn=LLONG_MAX;
int p=-1,q=-1;
int w=ceil(sqrt(1000000000/n))/2;
for(int i=max(x-w,1);i<=max(x-w,1)+2*w;i++)
{
for(int j=max(y-w,1);j<=max(y-w,1)+2*w;j++)
{
long long res=calc(i,j);
if(res<minn||res==minn&&i+j<p+q)
{
minn=res;
p=i;
q=j;
}
}
}
cout<<p<<" "<<q<<endl;
return 0;
}