Happy Ake, Ake has DIV3
Contest connection: https://codeforces.com/contest/1462
This game is pretty simple.
table of Contents
D. Add to Neighbour and Remove
E2. Close Tuples (hard version)
F. The Treasure of The Segments
A. Favorite Sequence
Main idea:
Given a sequence, output the sequence left and right in the order of the questions
Question idea:
Water question, simulate according to the meaning of the question
Code:
ll n,m,p;
ll a[maxn];
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
for(int i=1;i<=n;i++) read(a[i]);
int l = 1,r = n;
while(l<r){
printf("%lld %lld ",a[l],a[r]);
l++;
r--;
}
if(l == r) printf("%lld\n",a[l]);
else printf("\n");
}
return 0;
}
B. Last Year's Substring
Main idea:
Give a string of numbers and ask if you can delete the substring at most once to make the final string "2020"
Question idea:
Consider at most one operation, so you can only delete the substring in the middle, so just judge the boundary.
Code:
ll n,m,p;
char s[maxn];
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
scanf("%s",s+1);
if(n<4) printf("NO\n");
else{
if(s[1] == '2' && s[2] == '0' && s[3] == '2' && s[4] == '0') printf("YES\n");
else if(s[1] == '2' && s[2] == '0' && s[3] == '2' && s[n] == '0') printf("YES\n");
else if(s[1] == '2' && s[2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
else if(s[1] == '2' && s[n-2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
else if(s[n-3] == '2' && s[n-2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
C. Unique Number
Main idea:
Ask if the sum of digits is equal to x, and the digits are different from each other, the smallest number
Question idea:
Considering that the numbers are different from each other, so a total of 2 to the 10th power is possible
Just enumerate in binary
Code:
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
int ans = 1e9+7;
for(int i=0;i<(1<<10);i++){
int res = 0,temp = 0;
for(int k=0;k<10;k++){
if(i>>k&1){
res += k;
a[++temp] = k;
}
}
if(res == n){
if(a[1] == 0) swap(a[1],a[2]);
int tempx = 0;
for(int k=1;k<=temp;k++) tempx = tempx*10+a[k];
ans = min(ans,tempx);
}
}
printf("%d\n",ans == mod?-1:ans);
}
return 0;
}
D. Add to Neighbour and Remove
Main idea:
Abstract: Given a sequence, ask how many segments you can divide into, so that the sum of each segment is equal.
The final answer is: n-number of segments
Question idea:
There is a simple way of thinking, directly considering the sum of the final state, then this sum must be a factor of the sum
Just check each and every one
Now consider what if the sum is large?
Here is a way to write interval dp, which has nothing to do with s.. The idea is quite simple. Consider that dp[i][k] represents the equal value of the first i divided into k segments.
Then get a n^3 violence, use map to optimize it
This makes me very dumb..
Code:
ll n,m,p;
ll num[maxn],sum[maxn];
int dp[3005][3005];
int pre[3005];
unordered_map<ll,int>mp[3005];
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
for(int i=1;i<=n;i++) {
read(num[i]);
sum[i] = sum[i-1]+num[i];
mp[i].clear();
}
int mx = 1;
for(int i=1;i<=n;i++)
for(int k=1;k<=n;k++)
dp[i][k] = -1;
for(int i=1;i<=n;i++){
dp[i][1] = sum[i];
for(int k=2;k<=i;k++){
int op = mp[k-1][sum[i]];
if(op) dp[i][k] = sum[i]-sum[op];
}
for(int k=1;k<=i;k++)
if(~dp[i][k]) mp[k][dp[i][k]+sum[i]] = i;
}
for(int i=n,k=0;i>=1;i--,k++){
if(dp[n][i]!=-1){
printf("%d\n",k);
break;
}
}
}
return 0;
}
E2. Close Tuples (hard version)
Main idea:
Given a sequence of length n, ask how many subsequences of length m satisfy the sequence maximum value-sequence minimum value <=k
Question idea:
Enumerate the minimum value of the final answer, and then judge the number of combinations
Assuming that the minimum value of the current enumeration is x, then you need to know how many [x, x+k] there are: this operation can also be done by taking double pointers. In order to simply write a tree array, the result can be divided into two if you think of it. ..
Then respectively enumerate the number of minimum values
Code:
ll n,m,p;
ll num[maxn];
ll sum[maxn];
int vis[maxn];
ll fac[maxn];
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}return ans;
}
ll cal(int m,int n){
if(m<n) return 0;
return ((fac[m]*qpow(fac[m-n],mod-2))%mod*(qpow(fac[n],mod-2))%mod)%mod;
}
void add(int pos){
while(pos <= n){
sum[pos] ++;
pos += pos&-pos;
}
}
ll GetSum(int pos){
ll ans = 0;
while(pos){
ans += sum[pos];
pos -= pos&-pos;
}return ans;
}
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);read(m);read(p);
for(int i=1;i<=n;i++) read(num[i]);
for(int i=1;i<=n;i++) sum[i] = 0,vis[i] = 0;
for(int i=1;i<=n;i++) vis[num[i]]++;
fac[0] = 1;
for(int i=1;i<=n;i++) fac[i] = (fac[i-1]*i)%mod;
for(int i=1;i<=n;i++) add(num[i]);
ll ans = 0;
for(int i=1;i<=n;i++){
if(vis[i]){
ll temp = GetSum(min(i+p,n)) - GetSum(i-1);
for(int k=1;k<=min(m,vis[i]*1ll);k++){
ans = (ans + (cal(vis[i],k)*cal(temp-vis[i],m-k))%mod)%mod;
}
}
}
printf("%lld\n",ans);
}
return 0;
}
F. The Treasure of The Segments
Main idea:
Define a line segment set to be good, if and only if there is a line segment that intersects all other line segments, at least delete a few line segments to make this line segment set good
Question idea:
The obvious idea is to enumerate which line segment makes this line segment set good
So what line segments are required to intersect the line segment, use [total number-the number of line segments intersecting with this line segment], which is the number of disjoint line segments
Finally, for the answer of each line segment, just take one min
There are many ways to do this question, because the coordinates are too large, and the chair tree is used to dynamically open the point (too lazy to discretize)
Code:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
struct node{
int a,b;
bool friend operator<(node a,node b){
if(a.a == b.a) return a.b < b.b;
return a.a < b.a;
}
}q[maxn];
int pre[maxn],suf[maxn];
ll sum[maxn];
int cnt = 0;
struct Tree{
int l,r,w;
}t[maxn*35];
int root[maxn];
void Insert(int &now,int pre,ll l,ll r,ll pos){
t[now = ++cnt] = t[pre];
t[now].w ++;
if(l == r) return ;
ll mid = (l+r)/2;
if(pos <= mid) Insert(t[now].l,t[pre].l,l,mid,pos);
else Insert(t[now].r,t[pre].r,mid+1,r,pos);
}
int Find(int now,ll l,ll r,ll x,ll y){
if(x<=l && y>=r) return t[now].w;
ll mid = (l+r)/2;
int ans = 0;
if(x<=mid) ans += Find(t[now].l,l,mid,x,y);
if(y>mid) ans += Find(t[now].r,mid+1,r,x,y);
return ans;
}
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
for(int i=1;i<=n;i++){
read(q[i].a);
read(q[i].b);
}
sort(q+1,q+1+n);
cnt = 0;
root[0] = 0;
for(int i=1;i<=n;i++){
pre[i] = Find(root[i-1],1,2e9,q[i].a,q[i].b);
Insert(root[i],root[i-1],1,2e9,q[i].b);
}
cnt = 0;
root[n+1] = 0;
for(int i=n;i>=1;i--){
suf[i] = Find(root[i+1],1,2e9,q[i].a,q[i].b);
Insert(root[i],root[i+1],1,2e9,q[i].a);
}
ll ans = INF;
for(int i=1;i<=n;i++)
ans = min(ans,n-1-pre[i]-suf[i]);
printf("%lld\n",ans);
}
return 0;
}