[[https://codeforces.com/gym/102569|比赛链接]]
====== 题解 ======
===== A. Array's Hash =====
=== 题意 ===
给定一个长度为$n$的数组,这么定义该数组的哈希值:每次从数组开头取出两个数,将后一个数减去前一个数得到的数值放入数组开头,如此重复,直到数组中只剩下一个数,最后这个数便为数组的哈希值。现在有$m$次操作,每次操作把一段区间的数加上$v$,要求输出每次操作后数组的哈希值
===题解===
显然数组的哈希值为$\sum_{i=1}^n{\left(-1\right)^\left(n-i\right)\times a_i}$
因此当区间左右端点奇偶性相同时对哈希值无贡献,奇偶性不同时如果区间左端点与$n$奇偶性相同则哈希值加$v$,否则减$v$
时间复杂度$O\left(n+m\right)$
===== B. Bonuses on a Line =====
=== 题意 ===
数轴上有 $n$ 份奖金,每份奖金的坐标为 $x_i$ ,总共有 $t$ 秒的时间,每秒可走 $1$ 的距离。初始在原点 $0$ 位置,问最多能获得多少份奖金?
=== 题解 ===
先向某一方向跑,然后再折返跑向另一方向。例如先向负方向跑,在每份奖金处,利用二分查找,找到能够折返跑到正方向的奖金的最大份数即可。
时间复杂度 $O\left(n\log n\right)$
=== 代码 ===
#include
using namespace std;
const int N=200005;
typedef long long ll;
vectorneg;
vectorpos;
int main(){
ll n,t;
scanf("%lld %lld",&n,&t);
for(ll i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
if(x<0) neg.push_back(-x);
else pos.push_back(x);
}
reverse(neg.begin(),neg.end());
neg.push_back(1e15);pos.push_back(1e15);
ll maxx=0;
for(ll i=0;i=neg[i]) maxx=max(maxx,i+1);
ll left=t-2*neg[i];
ll p=upper_bound(pos.begin(),pos.end(),left)-pos.begin()-1;
if(p>=0) maxx=max(maxx,i+1+p+1);
}
for(ll i=0;i=pos[i]) maxx=max(maxx,i+1);
ll left=t-2*pos[i];
ll p=upper_bound(neg.begin(),neg.end(),left)-neg.begin()-1;
if(p>=0) maxx=max(maxx,i+1+p+1);
}
printf("%lld",maxx);
return 0;
}
===== C. Manhattan Distance =====
===题意===
在直角坐标系中给定$n$整点$\left(-10^8\le x_i,y_i\le 10^8\right)$,可以得到$\frac{n\times \left(n-1\right)}{2}$个点对,将所有点对的哈密顿距离排序,要求输出第k大的哈密顿距离$\left(2\le n\le 100000,1\le k\le \frac{n\times \left(n-1\right)}{2}\right)$
===题解===
大概思路为二分答案$d$,统计哈密顿距离$\le d$的点对个数
首先,将坐标系顺时针旋转$45$度,放大$\sqrt{2}$倍,所以所有点坐标变为$\left(x-y,x+y\right)$,与某个点哈密顿距离$\le d$转化为在以该点为中心的边长为$2d$的网格正方形中
考虑用滑动窗口+树状树组统计答案,具体过程见代码
时间复杂度$O\left(\log\left(4\times 10^8\right) n\log n\right)$
===代码===
#include
#include
#include
#include
#include
#include
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
inline int read_int(){
int t=0;bool sign=false;char c=getchar();
while(!isdigit(c)){sign|=c=='-';c=getchar();}
while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
return sign?-t:t;
}
inline LL read_LL(){
LL t=0;bool sign=false;char c=getchar();
while(!isdigit(c)){sign|=c=='-';c=getchar();}
while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
return sign?-t:t;
}
#define lowbit(x) (x)&(-x)
const int MAXN=1e5+5;
struct Node{
int x,y;
bool operator < (const Node &b)const{
return xd){
int pos=lower_bound(Y+1,Y+m,node[j].y)-Y;
add(pos,-1);
j++;
}
int pos1=upper_bound(Y+1,Y+m,node[i].y+d)-Y-1;
int pos2=lower_bound(Y+1,Y+m,node[i].y-d)-Y-1;
int pos3=lower_bound(Y+1,Y+m,node[i].y)-Y;
ans+=query(pos1)-query(pos2);
add(pos3,1);
}
return ans;
}
int main()
{
n=read_int(),k=read_LL();
int x,y;
_rep(i,1,n){
x=read_int(),y=read_int();
node[i].x=x-y,node[i].y=x+y;
Y[i]=x+y;
}
sort(node+1,node+n+1);
sort(Y+1,Y+n+1);
m=unique(Y+1,Y+n+1)-Y;
int lef=1,rig=4e8,mid,ans=-1;
while(lef<=rig){
mid=lef+rig>>1;
if(Count(mid)
===== D. Lexicographically Minimal Shortest Path =====
===== E. Fluctuations of Mana =====
签到题
===== F. Moving Target =====
===== G. Nuts and Bolts =====
===== H. Tree Painting =====
===== I. Sorting Colored Array =====
===== J. The Battle of Mages =====
===== K. Table =====
===== L. The Dragon Land =====
===== M. Notifications =====
签到题
====== 总结 ======