A.一起奏响历史之音!
题意:
判断给定的音节序列是否仅由五声音调组成。
思路
签到题。
代码
点击查看代码
void solve() {
int n, f = 1;
for (int i = 1; i <= 7; i++) {
cin >> a[i];
if (a[i] == 1 || a[i] == 2 || a[i] == 3 || a[i] == 5 || a[i] == 6) {
} else {
f = 0;
}
}
if (f) {
cout<<"YES\n";
}else{
cout<<"NO\n";
}
}
B.能去你家蹭口饭吃吗
题意:
找出一个最大的x,满足x比数组中至少一半的数小。
思路
排序即可。
代码
点击查看代码
void solve() {
int n;
cin>>n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a+1,a+1+n,greater<>());
cout<<a[(n+1)/2]-1<<endl;
}
C.字符串外串
题意:
给定n,m,构造长度为n,可爱值为m的字符串。
思路
发现当n-m>26或n=m时,无法构造出字符串;否则按照n-m的大小来构造字符串,详细见代码。
代码
点击查看代码
void solve() {
int n, m;
cin >> n >> m;
if (m == n||n-m>26) {
cout << "NO\n";
return;
}
s="";
int k=n-m;
for(int i=0;i<n;i++){
s+='a'+i%k;
}
cout<<"YES\n";
cout<<s<<endl;
}
D.字符串里串
题意:
定义字符串s的可爱度k为这样的一个最大整数,使得存在长度为k的连续子串a、长度为k的不连续子序列b,满足a=b。特别地,若不存在符合要求的a,b,则可爱度为0。求字符串的可爱值
思路
无
代码
点击查看代码
无
E.一起走很长的路!
题意:
给定数组a,和区间[l,r],操作是任选一个元素增加1或者减少1。求怎样在最少的操作数下满足任意$i\in[l+1,r],a_i\le\displaystyle\sum_{j=l}^{i-1}a_j $。
思路
区间和很容易想到用前缀和来解决,令\(S_i=\displaystyle\sum_{j=1}^{i}a_j\),则有任意\(i\in[l+1,r],a_i\le S_{i-1}-S_{l-1}\Rightarrow S_{l-1}\le S_{i-1}-a_i\)。
记录数组\(c,c_i=S_{i-1}-a_i\)。
则我们只需改变数组c的区间[l+1,r]即可。由前缀和的性质可知,增大\(a_l\)是最优的操作,那么我们只要求区间[l+1,r]内的最小值,用数据结构去求c的区间最小值即可。
代码
点击查看代码
int ans = 0,n,m;
int a[N], b[N], c[N];
priority_queue<int, vector<int>, greater<int>>q;
vector<PII>g;
string s;
const int MAX_LEN =2e5 ;
int seg_tree[MAX_LEN << 2];
int seg_tree1[MAX_LEN << 2];
int Lazy[MAX_LEN << 2];
int arr[MAX_LEN];
//从下往上更新 节点
void push_up (int root) {
seg_tree[root] = max(seg_tree[root << 1], seg_tree[root << 1 | 1]); //最小值改min
seg_tree1[root] = min(seg_tree1[root << 1], seg_tree1[root << 1 | 1]);
}
//从上向下更新,左右孩子
void push_down (int root, int L, int R) {
if(Lazy[root]){
Lazy[root << 1] += Lazy [root];
Lazy[root << 1 | 1] += Lazy[root];
int mid = (L + R) >> 1;
seg_tree[root << 1] += Lazy[root] * (mid - L + 1);
seg_tree[root << 1 | 1] += Lazy[root] * (R - mid);
seg_tree1[root << 1] += Lazy[root] * (mid - L + 1);
seg_tree1[root << 1 | 1] += Lazy[root] * (R - mid);
Lazy[root] = 0;
}
}
//建树
//[L,R]就是对应arr数组里面的数
void build (int root, int L, int R) {
Lazy[root] = 0;
if(L == R) {
seg_tree[root] = arr[L];
seg_tree1[root] = arr[L];
return ;
}
int mid = (L + R) >> 1;
build(root << 1, L, mid);
build(root << 1 | 1, mid + 1, R);
push_up(root);
}
//区间查询
//查找区间[LL,RR]的最大/小值
int querymax (int root, int L, int R, int LL, int RR) {
if (LL <= L && R <= RR) return seg_tree[root];
push_down(root, L, R); //每次访问都去检查Lazy 标记
int Ans = 0;
int mid = (L + R) >> 1;
if(LL <= mid) Ans = max(Ans, querymax(root << 1, L, mid, LL, RR)); //最小值改min
if(RR > mid) Ans = max(Ans, querymax(root << 1 | 1, mid + 1, R, LL, RR)); //最小值改min
return Ans;
}
int querymin (int root, int L, int R, int LL, int RR) {
if (LL <= L && R <= RR) return seg_tree1[root];
push_down(root, L, R); //每次访问都去检查Lazy 标记
int Ans = 1e18;
int mid = (L + R) >> 1;
if(LL <= mid) Ans = min(Ans, querymin(root << 1, L, mid, LL, RR)); //最小值改min
if(RR > mid) Ans = min(Ans, querymin(root << 1 | 1, mid + 1, R, LL, RR)); //最小值改min
return Ans;
}
//区间修改 +-某值
//使得区间[LL,RR]的值都加上val
void update_Interval(int root, int L, int R, int LL, int RR, int val){
if (LL <= L && R <= RR) {
Lazy[root] += val;
seg_tree[root] += val * (R - L + 1);
seg_tree1[root] += val * (R - L + 1);
return ;
}
push_down(root, L, R);
int mid = (L + R) >> 1;
if (LL <= mid) update_Interval(root << 1, L, mid, LL, RR, val);
if (RR > mid) update_Interval(root << 1 | 1, mid + 1, R, LL , RR, val);
push_up(root);
}
//单点修改 可以改为某值,或者+-某值
//把pos位置的值改成val
void update(int root, int L, int R, int pos, int val) {
if(L == R){
seg_tree[root] = val; //点直接变为某值
seg_tree1[root] = val; //点直接变为某值
return ;
}
int mid = (L + R) >> 1;
if(pos <= mid) update(root << 1, L, mid, pos, val);
else update(root << 1 | 1, mid + 1, R, pos, val);
push_up(root);
}
void solve() {
int n, m;
cin >> n >> m;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=b[i-1]+a[i];
arr[i]=b[i-1]-a[i];
}
build(1,1,n);
for(int i=1;i<=m;i++){
int l,r;
cin>>l>>r;
if(l==r){
cout<<0<<endl;
}else{
int x=querymin(1,1,n,l+1,r)-b[l-1];
cout<<max(0ll,-x)<<endl;
}
}
}
F.一起找神秘的数!
题意:
对于给定的区间,从中选取两个整数,使得下式成立:x+y=(x or y)+(x and y)+(x xor y),求解有多少对答案。
思路
打表发现只有x=y时成立。
代码
点击查看代码
void solve() {
int n, f = 1;
cin>>n>>f;
cout<<f-n+1<<endl;
}
G.一起铸最好的剑!
题意:
给定\(n,m\),找到最接近\(n\)的\(m^k\)的k的最小值
思路
枚举即可。
代码
点击查看代码
void solve() {
int n, m,s=1;
cin>>n>>m;
if(m==1){
cout<<s<<endl;
return;
}
int p=m;
while(p*m<=n){
s++;
p*=m;
}
if(abs(p*m-n)<abs(p-n)){
s++;
}
cout<<s<<endl;
}
H.一起画很大的圆!
题意:
划定了一个矩形区域,在这个区域的边界选3个整点,使得三点画出的圆最大。
思路
随便画几个就知道了。
代码
点击查看代码
void solve() {
int a,b,c,d;
cin>>a>>b>>c>>d;
if(b-a>=d-c){
cout<<b<<' '<<d<<endl;
cout<<a<<' '<<d-1<<endl;
cout<<b-1<<' '<<d<<endl;
}else{
cout<<a<<' '<<c<<endl;
cout<<a+1<<' '<<d<<endl;
cout<<a<<' '<<c+1<<endl;
}
}
J.数据时间?
题意:
略
思路
照着题意写就行了,我稍微取了点巧。注意编号范围到了1e20。
代码
点击查看代码
int n,h, m,s=1;
cin>>n>>h>>m;
set<string> s1,s2,s3;
for(int i=1;i<=n;i++){
int hh,mm,dd;
string x,z;
cin>>x>>hh>>mm>>dd>>z;
if(hh==h&&mm==-m){
if(z>="07:00:00"&&z<="09:00:00"||
z>="18:00:00"&&z<="20:00:00"){
s1.insert(x);
}
if(z>="11:00:00"&&z<="13:00:00"){
s2.insert(x);
}
if(z>="22:00:00"&&z<="23:59:59"||
z>="00:00:00"&&z<="01:00:00"){
s3.insert(x);
}
}
}
cout<<s1.size()<<' '<<s2.size()<<' '<<s3.size()<<endl;
K.可以分开吗?
题意:
求蓝色连通块相邻的灰色块的数量的最小值。
思路
很简单的bfs,直接写就行了
代码
点击查看代码
int ans = 0,n,m;
int a[N][N], b[N][N], c[N][N];
priority_queue<int, vector<int>, greater<int>>q;
vector<PII>g;
int xx[4]={0,1,0,-1},yy[4]={1,0,-1,0};
void dfs(int x,int y){
b[x][y]=1;
for(int i=0;i<4;i++){
int X=x+xx[i];
int Y=y+yy[i];
if(X<1||Y<1||X>n||Y>m)continue;
if(a[X][Y]){
if(!b[X][Y]){
dfs(X,Y);
}
}else{
if(!c[X][Y]){
c[X][Y]=1;
ans++;
g.push_back({X,Y});
}
}
}
}
void solve() {
int s=1;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char x;
cin>>x;
a[i][j]=x-'0';
}
}
int mx=1e18;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]&&!b[i][j]){
ans=0;
dfs(i,j);
mx=min(mx,ans);
for(auto[x,y]:g){
c[x][y]=0;
}
g.clear();
}
}
}
cout<<mx<<endl;
}