The first line of the output file must contain a single integer k – the minimum number of clicks necessary to make the given selection. The following k lines must define the way to make such a selection. Each line should contain the number of file to be clicked on the corresponding step, and a prefix “Ctrl+” or “Shift+” (without quotation marks) where necessary.
1 ≤ n ≤ 105 .
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
#include <string>
#include <ctime>
#include <list>
#include <bitset>
typedef unsigned char byte;
#define pb push_back
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define pi acos(-1)
using namespace std;
const int maxn = 1e5 + 500;
char str[maxn];
int length , sum[maxn], dp[maxn];
vector<int>Q,Q2;
struct operation
{
int x;
int type;
};
operation nxt[maxn];
struct QueryData
{
int minv , minpos;
QueryData(int minv , int minpos)
{
this->minv = minv , this->minpos = minpos;
}
};
typedef int SgTreeDataType;
struct treenode
{
int L , R ;
SgTreeDataType minv , minpos;
void updata(SgTreeDataType v)
{
minv = v;
}
};
treenode tree[maxn * 4];
inline void push_up(int o)
{
if(tree[o*2].minv > tree[o*2+1].minv)
{
tree[o].minv = tree[o*2+1].minv;
tree[o].minpos = tree[o*2+1].minpos;
}
else
{
tree[o].minv = tree[o*2].minv;
tree[o].minpos = tree[o*2].minpos;
}
}
inline void build_tree(int L , int R , int o)
{
tree[o].L = L , tree[o].R = R,tree[o].minv = 1<<29 , tree[o].minpos = 0;
if(L == R) tree[o].minpos = L;
if (R > L)
{
int mid = (L+R) >> 1;
build_tree(L,mid,o*2);
build_tree(mid+1,R,o*2+1);
}
}
inline void updata(int QL,int QR,SgTreeDataType v,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) tree[o].updata(v);
else
{
int mid = (L+R)>>1;
if (QL <= mid) updata(QL,QR,v,o*2);
if (QR > mid) updata(QL,QR,v,o*2+1);
push_up(o);
}
}
inline QueryData query(int QL,int QR,int o)
{
int L = tree[o].L , R = tree[o].R;
if (QL <= L && R <= QR) return QueryData(tree[o].minv,tree[o].minpos);
else
{
int mid = (L+R)>>1;
if (QL <= mid && QR > mid)
{
QueryData a = query(QL,QR,2*o);
QueryData b = query(QL,QR,2*o+1);
if(a.minv < b.minv) return a;
else return b;
}
else if (QL <= mid) return query(QL,QR,2*o);
else return query(QL,QR,2*o+1);
}
}
void initiation()
{
memset( dp , 0 , sizeof(dp));
scanf("%d%s",&length,str+1);sum[0] = 0;
for(int i = 1 ; i <= length ; ++ i)
{
sum[i] = sum[i-1];
if(str[i] == ‘*‘)
{
Q.push_back(i);
}
else
{
sum[i] ++ ;
Q2.push_back(i);
}
}
}
void solve()
{
int sz = Q.size();
int ansL = Q[0],ansR = Q[0],ans=sz;
build_tree( 0 , sz - 1 , 1 );
for(int i = 0 ; i < sz ; ++ i) updata( i , i , sum[Q[i]] - i , 1);
for(int i = 0 ; i < sz - 1; ++ i)
{
QueryData y = query( i + 1 , sz - 1, 1);
int newans = i + 1 + sz + y.minv - sum[Q[i]];
if(newans < ans)
{
ans = newans;
ansL = i;
ansR = y.minpos;
}
}
printf("%d\n",ans);
if(ansL != ansR)
{
printf("%d\n",Q[ansL]);
printf("Shift+%d\n",Q[ansR]);
for(int i = 0 ; i < sz ; ++ i) if(i < ansL || i > ansR) printf("Ctrl+%d\n",Q[i]);
for(int i = 0 ; i < Q2.size() ; ++ i) if( Q2[i] < Q[ansR] && Q2[i] > Q[ansL]) printf("Ctrl+%d\n",Q2[i]);
}
else
{
printf("%d\n",Q[0]);
for(int i = 1 ; i < sz ; ++ i) printf("Ctrl+%d\n",Q[i]);
}
}
int main(int argc,char *argv[])
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
initiation();
if(Q.size() == 0) printf("0\n");
else if(Q.size() == 1) printf("1\n%d\n",Q[0]);
else if(Q.size() == 2) printf("2\n%d\nCtrl+%d\n",Q[0],Q[1]);
else solve();
return 0;
}