A.Anu Has a Function
略
B.Aerodynamic
略
C.Water Balance
vp的时候猜了一下结论,答案满足每个位置被操作恰好一次,那么显然就是对 ( i , ∑ j = 1 i a j ) (i,\sum_{j=1}^{i}a_j) (i,∑j=1iaj)的下凸壳上相邻两个点间操作即可,建出下凸壳就做完了。
vp完后看了一下题解的证明,挺有意思的。
最小化 a i a_i ai的字典序等价于最小化 p i = ∑ j = 1 i a j p_i=\sum_{j=1}^{i}a_j pi=∑j=1iaj的字典序。同样把 ( i , p i ) (i,p_i) (i,pi)画在平面上,令每个点那么每次操作 [ l , r ] [l,r] [l,r]相当于对 ∀ l ≤ i ≤ r , p i = p l − 1 + p r − p l − 1 r − l + 1 \forall l\leq i\leq r,p_i=p_{l-1}+\frac{p_r-p_{l-1}}{r-l+1} ∀l≤i≤r,pi=pl−1+r−l+1pr−pl−1,也就是说把 ( l , p l ) ∼ ( r , p r ) (l,p_l)\sim (r,p_r) (l,pl)∼(r,pr)替换为线段 ( ( l − 1 , p l ) , ( r , p r ) ) ((l-1,p_l),(r,p_r)) ((l−1,pl),(r,pr))对应整数横坐标上的点。注意到不论我们如何操作,任意时刻 ( i , p i ) (i,p_i) (i,pi)显然都会在初始的下凸壳上方(因为每次连接了两个下凸壳上方的点),那么显然直接操作为下凸壳就是最优的。
时间复杂度为 O ( n ) \mathcal O(n) O(n)。
#include <bits/stdc++.h>
#define FR first
#define SE second
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pr;
struct Point {
ll x,y;
Point() {
}
Point(ll a,ll b):x(a),y(b) {
}
Point operator - (Point b) {
return Point(x-b.x,y-b.y);}
};
ll cross(Point x,Point y) {
return x.x*y.y-x.y*y.x;
}
Point st[1000005];
int top;
void insert(Point p) {
while (top>1&&cross(p-st[top],st[top]-st[top-1])>=0) top--;
st[++top]=p;
}
int main() {
int n;
scanf("%d",&n);
ll s=0;
insert(Point(0,0));
for(int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
s+=x;
insert(Point(i,s));
}
for(int i=2;i<=top;i++) {
db v=(db)(st[i].y-st[i-1].y)/(st[i].x-st[i-1].x);
for(int j=st[i-1].x+1;j<=st[i].x;j++)
printf("%.10f\n",v);
}
return 0;
}
D. Around the World
题目中的异或可以理解为线性空间 Z 2 5 \mathbb{Z}_2^5 Z25下的加法。考虑删去所有与 1 1 1号点相连的边,得到若干个连通分量。
对于某个连通分量,若最终它仍与 1 1 1号点连通,那么根据一个经典的结论,在这个连通分量 ( V , E ) (V,E) (V,E)的内部的每个非平凡回路权值组成的线性子空间可以表示为 ∣ E ∣ − ∣ V ∣ + 1 |E|-|V|+1 ∣E∣