每日练习3

屎,我写了半个小时5000多字,503给我变成1500了。但是也算我自己记录了一遍,反正我也不会再看()

牛牛多校9

我开了签到题2但是卡住了,还有跟着佬混了一下第三题(两个小时就干了这点)

签到2 Kill The Monsters:

想了很多贡献贪心和二分,最后答案是类似暴力

直接优先队列每一个大的数然后统计累计值和现在开始全部aoe的加和,但是要注意可能在100 100 100的情况下最后面的tmp才是正确答案,也就是一次aoe不用(这个我忘记了或者说我根本没有这种意识)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int A[N];
int main()
{
    int n,k;
    cin >> n >> k;
    priority_queue<int> q;
    int max_v=0;
    for(int i=1;i<=n;i++) 
    {
        cin >> A[i];
        max_v=max(max_v,A[i]);
        q.push(A[i]);
    }
    if(k==1) {
        cout << max_v << endl;
        return 0;
    }
    
    int ans=0x3f3f3f3f;
    int tmp=0;
    while(!q.empty())  {
        int t=q.top();
        q.pop();
        ans=min(tmp+t,ans);
        if(t/k!=0) q.push(t/k);
        tmp++;
    }
    
    cout << min(ans,tmp) << endl;
    
    return 0;
}

2难.

贪心找可行复杂度解,题目比较模糊。类似数位dp的统计方式,找到边界的sqrt来确定边界,但是因为60位n的关系,要么用高精度,要么python,要么int128,大佬写的128,我需要后续自己琢磨一下,但是思路理解。

#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
int n;
string L, R;
int m_sqrt(__int128 x)
{
    int l = 0, r = 1e16;
    while (l < r)
    {
        __int128 mid = l + r + 1 >> 1;
        if (mid * mid <= x)
            l = mid;
        else
            r = mid - 1;
    }
    return r + 1;
}
__int128 get_sum(__int128 x, __int128 y)
{
    __int128 ls = m_sqrt(x), rs = m_sqrt(y);
    return ls * rs;
}
__int128 to_128(string s)
{
    __int128 x = 0;
    for (int i = 0; i < s.size(); i++)
        x = x * 10 + (s[i] - '0');
    return x;
}
__int128 solve(string &s)
{
    string l = s.substr(0, s.size() / 2), r = s.substr(s.size() / 2);
    string lim;
    while (lim.size() < s.size() / 2)
        lim += '9';
    __int128 limit = to_128(lim);
    __int128 lv = to_128(l);
    __int128 rv = to_128(r);
    __int128 res = 0;
    if (lv != 0)
        res += get_sum(lv - 1, limit);
    __int128 mid = m_sqrt(lv) - 1;
    if (mid * mid == lv)
        res += get_sum(0, rv);
    return res;
}
void print(__int128 x)
{
    string res;
    while (x)
        res += (x % 10 + '0'), x /= 10;
    reverse(res.begin(), res.end());
    if (!res.size())
        res = "0";
    cout << res << endl;
}
void del_1(string &s)
{
    for (int i = s.size() - 1; ~i; i--)
        if (s[i] == '0')
            s[i] = '9';
        else
        {
            s[i]--;
            break;
        }
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> L >> R, del_1(L), print(solve(R) - solve(L));
}

这下面是重写的,所以随便口胡一下凌晨两点睡觉了:

round776

a,送

#include <bits/stdc++.h>
using namespace std;
void solve()
{
    string s;
    char c;
    cin >> s >> c;
    for(int i=0;i<s.size();i++) {
        if(s[i]==c) {
            if(i%2==0 && (s.size()-i-1)%2==0) {
                cout << "YES" << endl;
                return;
            }
        }
    }
    cout << "NO" << endl;
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

b,敏感度不够,要么公式前面最大,要么后面的构造a-1最大

#include <bits/stdc++.h>
using namespace std;
void solve()
{
    int l,r,a;
    cin >> l >> r >> a;
    
    int ans=r/a+r%a;
    int max_v=r/a*a-1;
    if(max_v>=l) ans=max(ans,max_v/a+max_v%a);
    cout << ans << endl;
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

c. 主要是得要知道一堆排列只要我想,我就可以构造出一种
不重叠的排序方式,所以只要确定了排列我就确定了ans值,所以
我就排序找到排列的最小ans值和就好了
然后对于这些数再单独排序输出前一个后一个

#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef pair<int,pair<int,int>> PIII;
const int N=2e5+10;
bool cmp(const PIII &a,const PIII &b) {
    if(a.y.y!=b.y.y) {
        return a.y.y<b.y.y;
    }
    return false;
}
bool cmp2(const PIII &a,const PIII &b) {
    if(a.y.x!=b.y.x) {
        return a.y.x<b.y.x;
    }
    return false;
}
void solve()
{
    vector<PIII> A;
    int n,m;
    cin >> n >> m;
    for(int i=1;i<=m;i++) {
        int x,w;
        cin >> x >> w;
        A.push_back({i,{x,w}});
    }
    sort(A.begin(),A.end(),cmp);

    vector<PIII> B;
    int sum=0;
    for(int i=0;i<2*n;i++) {
        sum+=A[i].y.y;
        B.push_back(A[i]);
    }

    sort(B.begin(),B.end(),cmp2);
    cout << sum << endl;
    for(int i=0;i<n;i++) {
        cout << B[i].x << " " << B[2*n-i-1].x << endl;
    }
    cout << endl;
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

3.round966(div3)

a.错了一次没有处理n<3

#include <bits/stdc++.h>
using namespace std;
void solve()
{

    int a;
    cin >> a;
    string s=to_string(a);
    if(s[0]=='1' && s[1]=='0') {
        if(s.size()<3) {
            cout << "NO" << endl;
            return;
        }
        if(s[2]=='0'  || (s[2]=='1' && s.size()==3)) {
            cout << "NO" << endl;
            return;
        }
    }else {
        cout << "NO" << endl;
        return;
    }
    cout << "YES" << endl;
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

b.错了一次没有处理!flag

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int A[N];
bool st[N];
void solve()
{
    memset(st,0,sizeof st);
    int n;
    cin >> n;
    bool flag=false;
    for(int i=1;i<=n;i++) 
    {
        cin >> A[i];
        if(i!=1 && (st[A[i]-1]==false && st[A[i]+1]==false) && !flag) {
            flag=true;
            cout << "NO" << endl;
        }
        st[A[i]]=true;
    }
    if(!flag) cout << "YES" << endl;
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

c.错了一次没有考虑n!=size直接错

<1>首先size=n
<2>map存值,st记录有没有遍历,找所有关联的看是否相同,然后下一个
问题出现了,没有考虑反向相同的问题

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int A[N];
bool st[N];
void solve()
{
    int n;
    cin >> n;
    map<int,vector<int>> Hash;
    for(int i=0;i<n;i++)  {
        cin >> A[i];
        Hash[A[i]].push_back(i);
    }
    int m;
    cin >> m;
    while(m--) {
        memset(st,0,sizeof st);
        map<char,bool> judge;
        string s;
        cin >> s;
        if(s.size()!=n) {
            cout << "NO" << endl;
            // cout << "HELLO" << endl;
            continue;
        }
        bool flag=false;
        for(int i=0;i<s.size();i++) {
            if(st[i]) continue;
            if(judge[s[i]] && !flag) {
                cout << "NO" << endl;
                flag=true;
                break;
            }
            auto tt=Hash[A[i]];
            judge[s[i]]=true;
            for(int j=0;j<tt.size();j++) {
                int tmp=tt[j];
                st[tmp]=true;
                if(s[i]!=s[tmp] && !flag) {
                    cout << "NO" << endl;
                    flag=true;
                    break;
                }
            }
            if(flag) break;
        }
        if(!flag) cout << "YES" << endl;
    }
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

d.

每个L和R只能用一次但是不是区间只能一次,

LRLLR

LRLLRLLLLLR


12345
LRLLR    15   如果  3+12=15
我要尽可能找大的,因为找旁边的我不能往左必然更小

左边找L,右指针找R知道l=r

前缀和双指针扫一次

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int A[N],S[N];
void solve()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) {
        cin >> A[i];
        S[i]=S[i-1]+A[i];
    }
    string s;
    cin >> s;
    int len=s.size();
    int l=0,r=s.size()-1;
    int ans=0;
    while(l<r) {
        if(s[l]!='L') l++;
        if(s[r]!='R') r--;
        if(s[l]=='L' && s[r]=='R') {
            ans+=S[r+1]-S[l];
            l++,r--;
        }
    }
    cout << ans << endl;
    return;
}
signed main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

e.

题目描述抽象,二位差分+排序乘积算贡献

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int n,m,k;
// void insert(int x1,int y1,int x2,int y2,int c,vector<vector<int>> &b){
//     b[x1][y1]+=c;
//     b[x2+1][y1]-=c;
//     b[x2+1][y2+1]+=c;
//     b[x1][y2+1]-=c;

//     for(int i=1;i<=n;i++){
//         for(int j=1;j<=m;j++){
//             b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
//             printf("%d ",b[i][j]);
//         }
//         printf("\n");
//     }
//     cout << endl;
// }
void solve()
{
    cin >> n >> m >> k;
    vector<vector<int>> b(n+5,vector<int> (m+5));
    // b[0][0]=3;
    // cout << b[0][0] << endl;
    for(int i=1;i+k-1<=n;i++) {
        for(int j=1;j+k-1<=m;j++) {
            int x1=i,y1=j,x2=i+k-1,y2=j+k-1;
            // insert(x1,y1,x2,y2,1,b);
            b[x1][y1]+=1;
            b[x2+1][y1]-=1;
            b[x2+1][y2+1]+=1;
            b[x1][y2+1]-=1;
        }
    }

    vector<int> q,xing;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
            q.push_back(b[i][j]);
            // printf("%d ",b[i][j]);
        }
    }
    sort(q.begin(),q.end(),greater<int>());

    int m;
    cin >> m;
    for(int i=1;i<=m;i++) {
        int t;
        cin >> t;
        xing.push_back(t);
    }
    sort(xing.begin(),xing.end(),greater<int>());

    // cout << "down" << endl;
    long long ans=0;
    for(int i=0;i<xing.size() && i<q.size();i++) {
        ans+=xing[i]*q[i];
    }
        // cout << "down" << endl;
    cout << ans << endl;
    return;
}
signed main()
{
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

f.没写出来

好像是背包,明天补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值