# "Problem solving report" cf1602 (codeworks round #751 (Div. 1 + Div. 2))

This Div2 was a hell of a game, but the harvest was great (the remaining two questions of Div1 really couldn't be filled)

## A. Two Subsequences

Main idea of the title:

Split the string \ (S \) into two substrings \ (A \) and \ (B \), so that the dictionary order of \ (A \) is less than \ (B \).

Idea:

Directly make only the smallest letter in \ (S \) in the \ (A \) string and all remaining characters in \ (B \).

code:

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,t;
char str[N];
int pos;
{
pos=1;
scanf("%s",str+1);
n=strlen(str+1);
}
inline void Work()
{
for(int i=2;i<=n;i++)
if(str[i]<str[pos]) pos=i;
putchar(str[pos]),putchar(' ');
for(int i=1;i<=n;i++)
if(pos!=i) putchar(str[i]);
putchar('\n');
}
int main()
{
scanf("%d",&t);
while(t--)
{
Work();
}
return 0;
}


## B. Divine Array

Difficulty: \ (1100 \) (thinking problem)

Main idea of the title:

You have a sequence \ (S \). Each transformation will change the number of times in a sequence \ (a_i \) to its occurrence in \ (S \).

Ask the value of position \ (x \) after \ (k \) transformation

Idea:

It can be found that the sequence will be stable after a certain number of times. (the official explanation will be stable if it does not exceed \ (logn \) times). I use \ (n \) times here. Directly take the array simulation and record the value of each position of each transformation.

code:

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int a[N][N],cnt[N];
int n,T,q;
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i][0]);
}
inline void Work()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cnt[j]=0;
for(int j=1;j<=n;j++)
cnt[a[j][i-1]]++;
for(int j=1;j<=n;j++)
a[j][i]=cnt[a[j][i-1]];
}
scanf("%d",&q);
while(q--)
{
static int x,k;
scanf("%d%d",&x,&k);
printf("%d\n",a[x][min(k,n)]);
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
Work();
}
return 0;
}


## C. Array Elimination

Difficulty: \ (1300 \) (thinking problem)

Main idea of the title:

You have a sequence \ (S \) you can select \ (k \) values in the sequence at a time and subtract their bitwise AND. Please find all \ (k \) that can delete the sequence.

Idea:

We can decompose each number into bits under binary, and count the number of each \ (1 \) respectively. It can be proved that if we take the number of \ (k \) that is \ (1 \) in a bit, we can reduce the number of that person \ (k \), so \ (k \) must be a factor of the number of occurrences of that person. Therefore, we can directly enumerate the value \ (k\in[1,n] \) of \ (k \) to see if it is the divisor of all numbers.

code:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,S=30;
int t,n;
int a[N],cnt[S];
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
inline void Work()
{
for(int i=0;i<30;i++) cnt[i]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<30;j++)
if(a[i]>>j&1) cnt[j]++;
for(int i=1;i<=n;i++)
{
bool flag=true;
for(int j=0;j<30;j++)
if(cnt[j]%i!=0)
{
flag=false;
break;
}
if(flag) printf("%d ",i);
}
putchar('\n');
}
int main()
{
scanf("%d",&t);
while(t--)
{
Work();
}
return 0;
}


## D. Frog Traveler

Difficulty: \ (1900 \) (underworld question)

Main idea of the title:

You are a frog. You can jump \ (h\in[0,a_i] \) meters at the bottom of the well at the beginning. If you reach the position of \ (J \), you will fall \ (b_j \) meters. How many times do you have to jump at least to reach the position outside the well (\ (0 \).

Idea:

You can consider the method of optimizing the drawing of the line segment tree (see the code), establish a virtual point \ (i+n \) for each point, establish an edge with a weight of \ (0 \) from each point to its virtual point, and connect each virtual point \ (i+n \) to an edge with a weight of \ (i-b_i \). For \ (I \) an edge with a weight of \ (1 \) from \ (I \) to \ ([i + 1, I + a_, I] \).

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10,M=N<<5;
int n,m;
int a[N],b[N];
int h[M],e[M],ne[M],w[M],idx;
int dis[M],pre[M];
bool vis[M];
inline void Add(int a,int b,int c)
{
e[++idx]=b;
ne[idx]=h[a];
h[a]=idx;
w[idx]=c;
}
namespace SegmentTree
{
struct node
{
int id;
#define id(x) unit[(x)].id
}unit[M];
int cnt;
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
#define mid (l+r>>1)
void Build(int k,int l,int r)
{
if(l==r) return (void)(id(k)=l+n+1);
id(k)=++cnt;
Build(lson(k),l,mid),Build(rson(k),mid+1,r);
}
void Update(int k,int l,int r,int L,int R,int st)
{
if(L<=mid) Update(lson(k),l,mid,L,R,st);
if(R>mid) Update(rson(k),mid+1,r,L,R,st);
}
}
using namespace SegmentTree;
deque<int> q;
inline void Bfs()
{
memset(dis,0X3f,sizeof(dis));
dis[n]=0,q.push_back(n);
while(q.size())
{
auto t=q.front();q.pop_front();
if(vis[t]) continue;
vis[t]=true;
for(int i=h[t];i;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+w[i])
{
dis[j]=dis[t]+w[i];
if(w[i]) q.push_back(j);
else q.push_front(j);
pre[j]=t;
}
}
}
}
{
scanf("%d",&n);
cnt=2*n+1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
}
vector<int> path;
inline void Work()
{
Build(1,0,n);
for(int i=1;i<=n;i++)
Update(1,0,n,i-a[i],i,i);
Bfs();
printf("%d\n",dis[0]==0X3f3f3f3f ? -1 : dis[0]);
if(dis[0]!=0X3f3f3f3f)
{
int now=0;
while(now!=n)
{
if(n+1<=now&&now<=2*n+1) path.push_back(now-n-1);
now=pre[now];
}
reverse(path.begin(),path.end());
for(auto x : path)
printf("%d ",x);
putchar('\n');
}
}
int main()
{
Work();
return 0;
}


## E. Optimal Insertion

Difficulty: \ (2300 \) (Yangjian question)

Main idea of the title:

You have A sequence \ (A \) and A sequence \ (B \). You should insert each element in the sequence \ (B \) anywhere in \ (A \) to minimize the reverse logarithm of the new sequence.

Idea:

It is easy to see A conclusion that after sorting the \ (B \) sequence, the answer to insert the \ (A \) sequence according to the relative position is the smallest, ((each element in \ (B \) will only contribute to the original elements of \ (A \) and will not contribute to its own elements). Then divide and conquer insertion can be considered. Insert \ (b_{mid} \) in the divide and conquer interval each time, find the position with the least contribution, and divide and conquer into two intervals after insertion. Note: multiple numbers can be inserted in one position!!!.

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int n,m,T;
int a[N],b[N],pos[N];
int suml[N],sumr[N];
vector<int> newa,nums;
void Solve(int lb,int rb,int la,int ra)
{
if(lb>rb) return;
int mid=lb+rb>>1;
suml[la-1]=0;
for(int i=la;i<=ra;i++)
{
suml[i]=sumr[i]=0;
if(a[i]>b[mid]) suml[i]++;
if(a[i]<b[mid]) sumr[i]++;
}
for(int i=la+1;i<=ra;i++) suml[i]+=suml[i-1];
for(int i=ra-1;i>=la;i--) sumr[i]+=sumr[i+1];
pos[mid]=la;
for(int i=la+1;i<=ra;i++)
if(suml[i-1]+sumr[i]<suml[pos[mid]-1]+sumr[pos[mid]])
pos[mid]=i;
Solve(lb,mid-1,la,pos[mid]),Solve(mid+1,rb,pos[mid],ra);
}
namespace BIT
{
int unit[N<<1],siz;
#define lowbit(x) ((x)&-(x))
inline void Clear(int x)
{
siz=x;
for(int i=1;i<=siz;i++) unit[i]=0;
}
{
for(x;x<=siz;x+=lowbit(x)) unit[x]+=val;
}
inline int Query(int x)
{
int res=0;
for(x;x;x-=lowbit(x)) res+=unit[x];
return res;
}
}
using namespace BIT;
{
scanf("%d%d",&n,&m);
nums.clear(),newa.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
nums.push_back(a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
nums.push_back(b[i]);
}
}
inline void Work()
{
sort(b+1,b+m+1);
sort(nums.begin(),nums.end());
nums.erase(unique(nums.begin(),nums.end()),nums.end());
for(int i=1;i<=n;i++) a[i]=lower_bound(nums.begin(),nums.end(),a[i])-nums.begin()+1;
for(int i=1;i<=m;i++) b[i]=lower_bound(nums.begin(),nums.end(),b[i])-nums.begin()+1;
Solve(1,m,1,n+1);
int now=m;
for(int i=n+1;i>=0;i--)
{
if(i!=n+1&&i!=0) newa.push_back(a[i]);
while(now&&pos[now]==i) newa.push_back(b[now--]);
}
ll ans=0;
Clear(nums.size());
for(auto x : newa)
{
ans+=Query(x-1);
}
printf("%lld\n",ans);

}
int main()
{
scanf("%d",&T);
while(T--)
{
Work();
}
return 0;
}


## F. Difficult Mountain

Difficulty: \ (2700 \) (hell greedy question)

Main idea of the title:

For a mountain, there is an initial \ (d \), there are \ (n \) people ready to climb the mountain, and there are two attributes \ (\ {s_i,a_i \} \) for each person. For each person \ (s_i \geq d \), they can climb the mountain and change \ (d \) to \ (max(d,a_i) \).

How many people can climb the mountain at most.

Idea:

Exclude the person whose initial \ (s_i \) is less than \ (d \). Greedy idea: sort according to \ (max(a_i,s_i) \) and then simulate statistics in order.

Proof: for classified discussion, if you now consider the \ (I \) person, if \ (s_i\geq a_i \), then \ (s_i\geq d \), this person can be selected and must be selected. If there is a person behind \ (max(a_j,s_j)=a_j \) and \ (s_j < a_i \) cannot be selected because of him, if this person must be selected, at least delete \ (I \) and because there must be $a_ j > a_ I$the answer will only get worse.

If \ (a_i > s_i \) and \ (I \) is selected, the same can be proved. If \ (I \) is not selected, it can be ignored.

code:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,d,idx;
struct PII
{
int s,a;
inline bool operator<(const PII &t) const
{
if(max(a,s)!=max(t.a,t.s)) return max(a,s)<max(t.a,t.s);
return s<t.s;
}
}que[N];
{
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)
{
static int s,a;
scanf("%d%d",&s,&a);
if(s<d) continue;
que[++idx]={s,a};
}
}
inline void Work()
{
sort(que+1,que+idx+1);
int ans=0;
for(int i=1;i<=idx;i++)
if(que[i].s>=d)
d=max(d,que[i].a),ans++;
printf("%d\n",ans);
}
int main()
{