Codeforces Round #737 (Div. 2)
A. Ezzat and Two Subsequences
- 题意
你可以将一个序列分成两边,(f(a))表示序列集合为(a)内所有数的平均值是多少?
然后求最大的(f(a) + f(b))
- 思路
记录最大值和总和即可算最大的。
code :
int a[N];
void solve(){
int n;
cin >> n;
int maxn = -INF, sum = 0;
fep(i,1,n) {
cin >> a[i];
maxn = max(maxn, a[i]);
sum += a[i];
}
db ans = maxn + 1.0 * (sum - maxn) / (n - 1);
pr("%.7f
",ans);
}
B. Moamen and k-subarrays
- 题意
给一个长度为(n)序列(a), 可以将他的子序列分成(k)个,你可以重新排列这k个序列后,然后满足整个序列有序即可。
- 思路
将整个序列离散化,然后判断前一个和后一个的大小即可
code :
vector<int> v;
int a[N];
void solve(){
int n,m;
cin >> n >> m;
v.clear();
for(int i = 1;i <= n;i ++) {
cin >> a[i];
v.pb(a[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
fep(i,1,n) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
int ans = n;
fep(i,2,n) if(a[i] == a[i - 1] + 1) ans --;
if(ans <= m) cout << "YES" << endl;
else cout << "NO" << endl;
}
C. Moamen and XOR
- 题意
给出(n,k),表示序列(a)长度为(n), 且每个(a_i <2 ^k)
问存在多少序列(a),满足:
(a_1 \,&\, a_2 \,&\, a_3 \,&\, ldots \,&\, a_n ge a_1 oplus a_2 oplus a_3 oplus ldots oplus a_n)
- 思路
首先对每个二进制来说,如果且操作为1,那么所有这一位都是1,而亦或操作只要出现奇数个1即可,那么就要分奇偶来判断了。
- 奇数不存在(a > b)的存在,只有(a <= b的情况),那么我们就只要算出相等的情况即可。
对于每个二进制要么都是0,要么都是1,那么1很简单,都是1,就一种情况。而0,就可以是各种情况了(C_n^0 + C_n^2 + C_n^4 cdots = 2^{n - 1})
那么奇数就是((2^{n-1} + 1)^k)。- 然后就要判偶数了的存在了。
那么偶数可以出现(a > b)的情况,那么我们就要枚举最高位的大小了,二进制中从最高位到最低位,第一个出现(a_i != b_i)的情况,然后后面的随意排都行,必须是(a_i > b_i),那么就(k)次枚举即可
然后相等的情况和上面的类似不过要减去一个(C_n^n), 因为全1的情况不同, 及((2^{n-1} - 1)^k)
即为ans = ((2^{n-1} - 1)^k + sum_{i=1}^k(2^{n-1} - 1)^{i-1} * (2^n)^{k-i})
code :
void solve(){
int n, k;
cin >> n >> k;
if(n & 1) {
ll ans = pow_mod(2,n - 1) + 1;
ans = pow_mod(ans, k);
cout << ans << endl;
}else {
ll d = pow_mod(2,n - 1) - 1;
ll c = pow_mod(2,n);
ll ans = pow_mod(d, k);
for(int i = 1;i <= k;i ++) {
ans = (ans + pow_mod(d, i - 1) * pow_mod(c, k - i) % mod + mod) % mod;
}
cout << ans << endl;
}
}
D. Ezzat and Grid
- 题意
给出一张01序列图,(n)行(10^9)列,让你取删最少的行,令任意一行,都存在某一列和其他行的某一列相同且都为1。求出需要删除的最少行。
- 思路
开线段树存储最大值即可,并多存一个行数,并开个(pre_i)记录前一个,找到相应最大的方案,那么其他就都删了满足最少。
code :
const int N = 600100;
#define mid (l + r >> 1)
#define lsn (u << 1)
#define rsn (u << 1 | 1)
vector<int> v;
int n,m;
struct node {
int id,l,r;
}q[N];
pii sum[N << 2], laz[N << 2];
void pushup(int u) {
sum[u] = max(sum[lsn], sum[rsn]);
}
void up(int u,pii k) {
sum[u] = max(sum[u], k);
laz[u] = max(laz[u], k);
}
void down(int u,int l,int r) {
if(!laz[u].first) return;
up(lsn,laz[u]);
up(rsn,laz[u]);
laz[u].first = laz[u].second = 0;
}
void update(int L,int R,pii v,int u,int l,int r) {
if(L <= l && R >= r) {
up(u,v);
return;
}
down(u,l,r);
if(L <= mid) update(L,R,v,lsn,l,mid);
if(R > mid) update(L,R,v,rsn,mid + 1,r);
pushup(u);
}
pii query(int L,int R,int u,int l,int r) {
if(L <= l && R >= r) {
return sum[u];
}
down(u,l,r);
if(R <= mid) return query(L,R,lsn,l,mid);
if(L > mid) return query(L,R,rsn,mid + 1,r);
return max(query(L,R,lsn,l,mid), query(L,R,rsn,mid + 1,r));
}
vector<pii> g[N];
int pre[N];
bool st[N];
void solve(){
cin >> n >> m;
for(int i = 1;i <= m;i ++) {
cin >> q[i].id >> q[i].l >> q[i].r;
v.push_back(q[i].l);
v.push_back(q[i].r);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int sz = v.size();
fep(i,1,m){
q[i].l = lower_bound(v.begin(), v.end(), q[i].l) - v.begin() + 1;
q[i].r = lower_bound(v.begin(), v.end(), q[i].r) - v.begin() + 1;
g[q[i].id].pb({q[i].l,q[i].r});
}
int flag = 0;
pii ans = pii{0,0};
for(int i = 1;i <= n;i ++) {
pii now = pii{0,0};
for(auto it : g[i]) {
now = max(now, query(it.first, it.second,1,1,sz));
}
pre[i] = now.second;
now = pii{now.first + 1, i};
for(auto it : g[i]) {
update(it.first,it.second,now,1,1,sz);
}
ans = max(ans, now);
}
cout << n - ans.first << endl;
int k = ans.second;
while(k) {
st[k] = 1;
k = pre[k];
}
for(int i = 1;i <= n;i ++) {
if(!st[i]) {
cout << i << ' ';
}
}
}