CodeForces - 798D Mike and distribution 想法题,数学证明

时间:2023-03-09 13:40:33
CodeForces - 798D Mike and distribution 想法题,数学证明

题意:给你两个数列a,b,你要输出k个下标,使得这些下标对应的a的和大于整个a数列的和的1/2.同时这些下标对应的b

//题解:首先将条件换一种说法,就是要取floor(n/2)+1个数使得这些数大于剩下的数。然后想到两种取法,一种是排好序选前半段。令一种取法是两个两个分组,每组取大的那个。
//然后就可以(很困难地)想到一种巧妙的取法,先用一个结构体保存a,b,idx,按照a从大到小排序,先取第一个,再对剩下的每两个一组取其中b更大的。这样保证了被选出
//的b一定大于剩下的b,也就满足了条件。然后考虑a,按照前面的分组,每组的a并不一定选到了大的。但是我们(并没有)观察到第一个选的a (也就是a的最大值)一定大于第一组没选到的那个a、第一组选的a一定大于第二组没选出的a···;
//同理这样选出的a也一定大于剩下的a。所以算法就是读取,排序,一个循环 。(codeforces上python只有三行。。。)

ac代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + ;
struct node { int a, b, idx; }s[maxn];
bool cmp(node x,node y) {
return x.a > y.a;
}
int main() {
int n;
cin >> n;
for (int i = ; i <= n; i++) {
scanf("%d", &s[i].a);
s[i].idx = i;
}
for (int i = ; i <= n; i++) {
scanf("%d", &s[i].b);
} sort(s + , s + + n,cmp);
cout << n / +<<endl;
cout << s[].idx;
for (int i = ; i <= n; i += ) {
int ans;
s[i].b > s[i + ].b ? ans = s[i].idx : ans=s[i + ].idx;
printf(" %d", ans);
}
//cin >> n; }

附 :codeforces上看到的神级头文件,

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <complex>
#include <bitset>
#include <cmath> using namespace std; #define mst(x,v) memset(x,v,sizeof(x))
#define rp(k,x,v) for(int k = x;k<v;++k)
#define rps(s) for(int i = 0;s[i];++i)
#define RP(k,x,v) for(int k = x;k<=v;++k)
#define lp(k,x,v) for(int k = x;k>v;--k)
#define LP(k,x,v) for(int k = x;k>=v;--k)
#define ll long long
#define ull unsigned long long
#define fr(file) freopen(file,"r",stdin);
#define fw(file) freopen(file,"w",stdout);
#define lowbit(x) (x&-x)
#define adde(u,v) edg[++ecnt]=Edge(u,v,g[u]),g[u]=ecnt
#define addew(u,v,w) edg[++ecnt]=Edge(u,v,g[u],w),g[u]=ecnt
#define addedg(u,v,w,cap) edg[++ecnt]=Edge(u,v,g[u],w,cap),g[u]=ecnt,edg[++ecnt]=Edge(v,u,g[v],-w,0),g[v]=ecnt
#define fson for(int i = g[u];~i;i=edg[i].next)
#define LB lower_bound
#define UB upper_bound
#define inp(n,a) RP(i,1,n) ru(a[i]);
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pdd pair<double,double>
#define piii pair<pii,int>
#define plll pair<pll,ll>
#define mpt int mid = l+r>>1;
#define ls (k<<1)
#define rs (k<<1|1)
#define INF (1<<28)
#define LINF (1LL << 60)
#define initi(n,a) RP(i,1,n) a[i]=INF;
#define initl(n,a) RP(i,1,n) a[i]=LINF;
#define dsui(n,p) RP(i,1,n) p[i]=i;
#define all(a) a.begin(),a.end()
#define inr (ql<=l && r<=qr)
#define cpx complex<double>
#define spf(s,a) RP(i,1,n) s[i]=s[i-1]+a[i]
#define ssf(s,a) lp(i,n,0) g[i]=g[i+1]+a[i]
#define upmax(a,b) a=max(a,b)
#define upmin(a,b) a=min(a,b)
#define getmax(maxd,a,n) RP(i,1,n) upmax(maxd,a[i])
#define getmin(mind,a,n) RP(i,1,n) upmin(mind,a[i]) char READ_DATA;
int SIGNAL_INPUT;
template <typename Type>
inline Type ru(Type &v)
{
SIGNAL_INPUT = ;
while ((READ_DATA = getchar()) < '' || READ_DATA > '')
if (READ_DATA == '-')
SIGNAL_INPUT = -;
else if (READ_DATA == EOF)
return EOF;
v = READ_DATA - '';
while ((READ_DATA = getchar()) >= '' && READ_DATA <= '')
v = v * + READ_DATA - '';
v *= SIGNAL_INPUT;
return v;
}
template<typename A, typename B > inline char ru(A&x, B&y) { if (ru(x) == EOF) return EOF; ru(y); return ; }
template<typename A, typename B, typename C>inline char ru(A&x, B&y, C&z) { if (ru(x) == EOF) return EOF; ru(y); ru(z); return ; }
template<typename A, typename B, typename C, typename D>inline char ru(A&x, B&y, C&z, D&w) { if (ru(x) == EOF) return EOF; ru(y); ru(z); ru(w); return ; }
int TEMP;
inline void swap(int &a, int &b)
{
TEMP = a;
a = b;
b = TEMP;
}
struct Vector
{
double x, y;
Vector(double _x = 0.0, double _y = 0.0)
{
x = _x;
y = _y;
}
int operator<(const Vector &cmp) const
{
return x < cmp.x || (x == cmp.x && y < cmp.y);
}
};
typedef Vector Point;
inline double dis(Point &a, Point &b)
{
return sqrt(pow(a.x - b.x, ) + pow(a.y - b.y, ));
} struct Edge
{
int u, v, next;
int w;
int cap, flow;
Edge(int _u = , int _v = , int nxt = -, int _w = , int _cap = )
{
u = _u;
v = _v;
w = _w;
cap = _cap;
flow = ;
next = nxt;
} int operator<(const Edge &b) const
{
return w < b.w;
}
}; namespace BalancedTreeNode
{
struct Node
{
Node *ch[], *fa;
int v, s, rev, setv, sum, lsum, rsum, mxsum; Node(int val = )
{
v = sum = val;
s = rev = ;
lsum = rsum = val;
mxsum = val;
setv = INF;
} int cmpv(int val)
{
return val == v ? - : val>v;
} int cmprk(int rk)
{
return rk == ch[]->s + ? - : rk > ch[]->s + ;
} void pushdown()
{
if (rev)
{
swap(ch[], ch[]);
swap(lsum, rsum);
if (ch[]->v != -INF) ch[]->rev ^= ;
if (ch[]->v != -INF) ch[]->rev ^= ;
rev = ;
} if (setv != INF)
{
v = setv;
lsum = rsum = mxsum = max(v, sum = v*s);
if (ch[]->v != -INF) ch[]->setv = setv;
if (ch[]->v != -INF) ch[]->setv = setv;
setv = INF;
}
} void maintain()
{
pushdown();
ch[]->pushdown(); ch[]->pushdown();
s = ch[]->s + ch[]->s + ;
sum = ch[]->sum + ch[]->sum + v;
lsum = rsum = -INF;
mxsum = -INF;
upmax(lsum, max(ch[]->lsum, ch[]->sum + v + max(, ch[]->lsum)));
upmax(rsum, max(ch[]->rsum, ch[]->sum + v + max(, ch[]->rsum)));
upmax(mxsum, max(, ch[]->rsum) + v + max(, ch[]->lsum));
upmax(mxsum, max(ch[]->mxsum, ch[]->mxsum));
} };
Node* null = new Node(-INF); Node* newnode(int val)
{
Node* k = new Node(val);
k->ch[] = k->ch[] = k->fa = null;
k->maintain();
return k;
}
inline void rotate(Node *x, const int d)
{
Node* y = x->fa;
y->ch[d ^ ] = x->ch[d];
if (x->ch[d] != null) x->ch[d]->fa = y;
x->fa = y->fa;
if (y->fa->ch[] == y) x->fa->ch[] = x;
else if (y->fa->ch[] == y) x->fa->ch[] = x;
y->fa = x;
x->ch[d] = y;
y->maintain();
x->maintain();
} Node* insert(Node* &k, int val)
{
if (k == null)
return k = newnode(val);
else
{
int d = k->cmpv(val);
if (d == -) return k;
int reach = k->ch[d] == null;
Node* p = insert(k->ch[d], val);
k->maintain();
if (reach) k->ch[d]->fa = k;
return p;
}
} void Remove_Tree(Node* k)
{
if (k->ch[] != null) Remove_Tree(k->ch[]);
if (k->ch[] != null) Remove_Tree(k->ch[]);
delete k;
} int Rank(Node *k, int val)
{
int rk = , d;
while (k != null)
{
k->pushdown();
d = k->cmpv(val);
if (d) rk += k->ch[]->s + ;
if (d == -) break;
k = k->ch[d];
}
return rk;
} Node* Kth(Node* k, int rk)
{
int d;
while (k != null)
{
k->pushdown();
d = k->cmprk(rk);
if (d == -)
return k;
if (d) rk -= k->ch[]->s + ;
k = k->ch[d];
}
return null;
}
}
namespace Splay
{
using namespace BalancedTreeNode; inline int isfa(Node *x, Node* &y)
{
return (y = x->fa) != null && (y->ch[] == x || y->ch[] == x);
}
inline void splay(Node* x)
{
x->pushdown();
Node *y, *z;
while (isfa(x, y))
{
if (isfa(y, z))
{
z->pushdown(); y->pushdown(); x->pushdown();
int d = y == z->ch[];
if (x == y->ch[d]) rotate(x, d ^ ), rotate(x, d);
else rotate(y, d), rotate(x, d);
}
else
{
y->pushdown(); x->pushdown();
rotate(x, x == y->ch[]);
break;
}
}
} inline void Insert(Node* &k, int val)
{
splay(k = insert(k, val));
} Node* build(int *a, int l, int r)
{
if (l > r) return null;
mpt;
Node* k = newnode(a[mid]);
k->ch[] = build(a, l, mid - );
k->ch[] = build(a, mid + , r);
if (k->ch[] != null) k->ch[]->fa = k;
if (k->ch[] != null) k->ch[]->fa = k;
if (mid == )
k->sum = ;
k->maintain(); return k;
} Node* merge(Node *left, Node *right)
{
splay(left = Kth(left, left->s));
left->ch[] = right;
right->fa = left;
left->maintain();
return left;
} void split(Node *k, int rk, Node* &left, Node* &right)
{
splay(k = Kth(k, rk));
left = k;
right = left->ch[];
left->ch[] = null;
right->fa = null;
left->maintain();
}
};
namespace LCT
{
using namespace Splay; Node* access(Node* k)
{
Node* p = null;
while (k != null)
{
splay(k);
k->ch[] = p;
p = k; k->maintain();
k = k->fa;
}
return p;
} void makeroot(Node* k)
{
access(k)->rev ^= ;
splay(k);
} Node* getroot(Node* k)
{
k = access(k);
k->pushdown();
while (k->ch[] != null)
{
k = k->ch[];
k->pushdown();
}
return k;
} void link(Node* x, Node* y)
{
makeroot(x);
x->fa = y;
access(x);
} void cut(Node* x, Node* y)
{
makeroot(x);
access(y); splay(y);
y->ch[]->fa = null;
y->ch[] = null;
y->maintain();
}
}
ll gcd(ll a, ll b)
{
while (b)
{
a %= b;
swap(a, b);
}
return a;
}
void exgcd(ll a, ll b, ll &d, ll &x, ll &y)
{
if (!b) d = a, x = , y = ;
else exgcd(b, a%b, d, y, x), y -= x*(a / b);
}
ll inv(ll a, ll mod)
{
ll d, x, y;
exgcd(a, mod, d, x, y);
return d == ? (x + mod) % mod : -;
}
int bitcnt(ll x)
{
int cnt = ;
while (x)
{
cnt += (x & );
x >>= ;
}
return cnt;
}
ll key = ;
ll mod = 1e9 + ;
ll qkmul(ll a, ll b)
{
ll ans = , x = a;
while (b)
{
if (b & ) (ans += x) %= mod;
(x += x) %= mod;
b >>= ;
}
return ans;
}
ll qkpow(ll a, ll b)
{
ll ans = , x = a;
while (b)
{
if (b & ) (ans *= x) %= mod;
(x *= x) %= mod;
b >>= ;
}
return ans;
}
const int maxn = 1e5 + , maxp = 1e6;
const double pi = acos(-1.0), alpha = 0.65, eps = 1e-;
inline int dcmp(double a, double b) { return abs(a - b) < eps; }
struct DSU
{
int p[maxn]; void init(int n)
{
RP(i, , n) p[i] = i;
} int find(int u)
{
return u == p[u] ? u : p[u] = find(p[u]);
} void merge(int u, int v)
{
u = find(u); v = find(v);
p[u] = (u^v) ? v : p[u];
}
};
struct BIT
{
ll *t, n; void init(int sz)
{
t = new ll[sz + ];
memset(t, , sizeof(ll)*(sz + ));
n = sz;
} void add(int x, ll d)
{
while (x <= n)
{
t[x] += d;
x += lowbit(x);
}
} ll qry(int x)
{
ll ans = ;
while (x)
{
ans += t[x];
x -= lowbit(x);
}
return ans;
} int qry(int l, int r)
{
return qry(r) - qry(l - );
}
};
int N;
struct SegTree
{
struct Node
{
int lc, rc;
ll sum, add;
}t[maxn * ]; void maintain(int k,int l,int r)
{
int lc = t[k].lc, rc = t[k].rc;
(t[k].sum = t[lc].sum + t[rc].sum + t[k].add*(r - l + ) % mod) %= mod;
} void pushdown(int k,int l,int r)
{
if (t[k].add)
{
if (l == r)
{
t[k].sum += t[k].add;
t[k].add = ;
return;
}
mpt;
int lc = t[k].lc, rc = t[k].rc;
(t[lc].add += t[k].add)%=mod; maintain(lc, l, mid);
(t[rc].add += t[k].add)%=mod; maintain(rc, mid + , r);
t[k].add = ;
}
} int ql, qr, tot;
ll qv;
void init(int _N)
{
N = _N;
tot = ;
} void build(int k = , int l = , int r = N)
{
if (l == r)
return;
else
{
mpt;
build(t[k].lc = ++tot, l, mid);
build(t[k].rc = ++tot, mid + , r);
}
} void add(int k = , int l = , int r = N)
{
if (inr)
{
(t[k].add += qv) %= mod;
}
else
{
mpt;
if (ql <= mid)
add(t[k].lc, l, mid);
if (qr > mid)
add(t[k].rc, mid + , r);
}
maintain(k, l, r);
} ll qry(int k = , int l = , int r = N,ll add=)
{
if (inr)
{
return (t[k].sum + add*(r - l + ) % mod) % mod;
}
else
{
mpt;
ll ans = ;
add += t[k].add;
if (ql <= mid)
(ans += qry(t[k].lc, l, mid, add)) %= mod;
if (qr > mid)
(ans += qry(t[k].rc, mid + , r, add)) %= mod;
return ans;
}
} void Add(int l, int r, ll v)
{
ql = l; qr = r; qv = v;
add();
} ll Qry(int l, int r)
{
ql = l; qr = r;
return qry();
}
};
struct MCMF
{
int n, m, s, t;
Edge edg[maxn];
int ecnt, g[maxn], d[maxn], a[maxn], inq[maxn], pre[maxn]; void init(int N)
{
n = N;
mst(g, ecnt = -);
} void addedge(int u, int v, int w, int cap)
{
addedg(u, v, w, cap);
} queue<int> q;
int bfs()
{
RP(i, , n) d[i] = INF;
q.push(s);
int u, v;
d[s] = ;
inq[s] = ;
a[s] = INF;
while (!q.empty())
{
u = q.front(); q.pop();
fson
{
v = edg[i].v;
if (edg[i].cap>edg[i].flow && d[v] > d[u] + edg[i].w)
{
d[v] = d[u] + edg[i].w;
a[v] = min(a[u], edg[i].cap - edg[i].flow);
pre[v] = i;
if (!inq[v])
{
q.push(v);
inq[v] = ;
}
}
}
inq[u] = ;
} return d[t] != INF;
} void augment(int &cost)
{
cost += a[t] * d[t];
int u = t;
while (u != s)
{
edg[pre[u]].flow += a[t];
edg[pre[u] ^ ].flow -= a[t];
u = edg[pre[u]].u;
}
} int mcmf(int S, int T)
{
s = S; t = T;
int cost = ;
while (bfs())
{
augment(cost);
}
return cost;
}
};
struct Dinic
{
int n, m, s, t;
Edge edg[maxn];
int ecnt, g[maxn], d[maxn], vis[maxn], cur[maxn]; void init(int N)
{
n = N;
mst(g, ecnt = -);
} void addedge(int u, int v, int cap)
{
addedg(u, v, , cap);
} queue<int> q;
int bfs()
{
mst(vis, );
q.push(s);
int u, v;
vis[s] = ;
while (!q.empty())
{
u = q.front(); q.pop();
fson
{
v = edg[i].v;
if (edg[i].cap>edg[i].flow && !vis[v])
{
d[v] = d[u] + ;
vis[v] = ;
q.push(v);
}
}
} return vis[t];
} int dfs(int u, int a)
{
if (u == t || !a)
return a; int flow = , aug, v;
for (int &i = cur[u]; ~i; i = edg[i].next)
{
v = edg[i].v;
if (d[v] == d[u] + && (aug = dfs(v, min(a, edg[i].cap - edg[i].flow))))
{
flow += aug;
a -= aug;
edg[i].flow += aug;
edg[i ^ ].flow -= aug;
if (!a) break;
}
}
return flow;
} int maxflow(int S, int T)
{
s = S, t = T;
int flow = ;
while (bfs())
{
RP(i, , n) cur[i] = g[i];
flow += dfs(s, INF);
}
return flow;
}
};
struct Mat
{
int n, m;
ll a[][]; Mat(int r = , int c = )
{
n = r; m = c;
mst(a, );
} static Mat idmat(int n)
{
Mat ans(n, n);
rp(i, , n) ans[i][i] = ;
return ans;
} ll* operator[](int i)
{
return a[i];
} Mat operator*(Mat b)
{
Mat ans(n, b.m);
rp(i, , n)
rp(j, , b.m)
rp(k, , m)
(ans[i][j] += a[i][k] * b[k][j] % mod) %= mod;
return ans;
}
};
Mat qkpow(Mat &A, ll b)
{
Mat ans = Mat::idmat(A.n), x = A;
while (b)
{
if (b & ) ans = ans * x;
x = x*x;
b >>= ;
}
return ans;
} int n, a[maxn], b[maxn], c[maxn]; int cmp(const int &i, const int &j)
{
return a[i] > a[j];
} int main()
{
ru(n); inp(n, a); inp(n, b);
RP(i, , n) c[i] = i;
sort(c + , c + n + , cmp);
printf("%d\n%d", n / + , c[]);
for (int i = ; i <= n; i += )
{
if (b[c[i]] > b[c[i + ]])
printf(" %d", c[i]);
else
printf(" %d", c[i + ]);
}
}

的和也大于整个b数列的和的1/2.k<= CodeForces - 798D Mike and distribution 想法题,数学证明.(这个条件很关键)

//题解:首先将条件换一种说法,就是要取floor(n/2)+1个数使得这些数大于剩下的数。然后想到两种取法,一种是排好序选前半段。令一种取法是两个两个分组,每组取大的那个。
//然后就可以(很困难地)想到一种巧妙的取法,先用一个结构体保存a,b,idx,按照a从大到小排序,先取第一个,再对剩下的每两个一组取其中b更大的。这样保证了被选出
//的b一定大于剩下的b,也就满足了条件。然后考虑a,按照前面的分组,每组的a并不一定选到了大的。但是我们(并没有)观察到第一个选的a (也就是a的最大值)一定大于第一组没选到的那个a、第一组选的a一定大于第二组没选出的a···;
//同理这样选出的a也一定大于剩下的a。所以算法就是读取,排序,一个循环 。(codeforces上python只有三行。。。)

ac