CF#R582(div 3)总结

先吐槽一下学校,为什么要在8.31开学啊,打了一半心态崩了

就退了,想着应该不会掉很多的.....................................

气死了,补一下题解吧(题解是后来补的,花了差不多俩小时)

A - Chips Moving

很容易想到,这个东西可以直接统计每个数字是奇数还是偶数的出现次数,取较小值即可

#include<bits/stdc++.h>
using namespace std;
#define LL long long
int a,n,m,p,q;
int ans;
int main()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        int x;cin>>x;
        if (x&1) p++;
        else q++;
    }
    printf("%d
",min(p,q));
    return 0;
}

B. Bad Prices

本来想的是用树状数组直接维护一下,但是懒得写离散化,手玩数据发现,当前点只需要看后面有没有数比它小即可,倒着扫描即可

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
const int N=2e5+7;
int tree[N];
int T;
int ans,m,n;
int a[N],p[N];
int main()
{
    cin>>T;
    while (T--)
    {
        cin>>n;ans=0;
        for (int i=1;i<=n;i++) cin>>a[i];int mn=a[n];
        for (int i=n-1;i>=1;i--)
        {
            if (a[i]>mn) {ans++;}
            else {mn=min(mn,a[i]);continue;}
        }
        printf("%d
",ans);
    }
    return 0;
}

C. Book Reading

对于每个数字肯定有一定的循环节,我们先处理出他需要的循环次数,对于循环节直接暴力计算即可

写的时候犯傻了,懒得找规律,就直接全算了一遍,好像可以分质数非质数分类的(雾

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL ans;
LL m,n,T;
int main()
{
    cin>>T;
    while (T--)
    {
        cin>>n>>m;
        LL p=m%10;ans=p;LL tm=n/m;
        if (p==1)
        {
            ans=(tm/10)*45;
            for (int i=1;i<=tm%10;i++) ans+=i;
        }
        if (p==2)
        {
            ans=(tm/5)*20;
            for (int i=1;i<=tm%5;i++) ans+=i*2;
        }
        if (p==3)
        {
            ans=(tm/10)*(45);LL k=3;
            for (int i=1;i<=tm%10;i++)
            {
                ans+=k;
                k=(k+3)%10;
            }
        }
        if (p==4)
        {
            ans=(tm/5)*(20);LL k=4;
            for (int i=1;i<=tm%5;i++)
            {
                ans+=k;
                k=(k+4)%10;
            }
        }
        if (p==5)
        {
            ans=(tm/2)*(5);LL k=5;
            for (int i=1;i<=tm%2;i++)
            {
                ans+=k;
                k=(k+5)%10;
            }
        }
        if (p==6)
        {
            ans=(tm/5)*(20);LL k=6;
            for (int i=1;i<=tm%5;i++)
            {
                ans+=k;
                k=(k+6)%10;
            }
        }
        if (p==7)
        {
            ans=(tm/10)*(45);LL k=7;
            for (int i=1;i<=tm%10;i++)
            {
                ans+=k;
                k=(k+7)%10;
            }
        }
        if (p==8)
        {
            ans=(tm/5)*(20);LL k=8;
            for (int i=1;i<=tm%5;i++)
            {
                ans+=k;
                k=(k+8)%10;
            }
        }
        if (p==9)
        {
            ans=(tm/10)*(45);LL k=9;
            for (int i=1;i<=tm%10;i++)
            {
                ans+=k;
                k=(k+9)%10;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

D2. Equalizing by Division 

这题有毒,本来考场上直接可以写开的,我非要用堆维护,我是zz,所以就一直调不出来,气死人了

其实我们对于每个值,直接将其分解,布数计入到一个数组即可,最后扫描一遍去最小值即可

#include<bits/stdc++.h>
#define I inline
using namespace std;
const int N=2e5+7;
const int INF=0x7f7f7f7f;
vector<int> v[N];
int n,k,a[N],st;
I int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void solve(int x)
{
    int cnt=0;
    while (x)
    {
        v[x].push_back(cnt);
        x>>=1;
        cnt++;
    }
}
int main()
{
    n=read(),k=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++) solve(a[i]),st=max(st,a[i]);
    int ans=INF;
    for (int i=0;i<=st;i++)
    {
        if (v[i].size()<k) continue;
        sort(v[i].begin(),v[i].end());
        ans=min(ans,accumulate(v[i].begin(),v[i].begin()+k,0));
    }
    cout<<ans;
    return 0;
}

E. Two Small Strings

不清楚题解什么意思,自己YY了个算法:

我们考虑三个字符排列的每种情况,只有6种,先对其进行判断看看可以不可以自己首位相连

如果不行,那么判断自己本身涵盖题目所给字符,直接暴力输出自己每个字符N遍即可

#include<bits/stdc++.h>
using namespace std;
string s[7],sp;
int n,Q;
bool vis[7];
int main()
{
    s[1]="abc",s[2]="acb",s[3]="bca",s[4]="bac",s[5]="cab",s[6]="cba";
    cin>>n;
    string ss[3];
    int pos=0;
    cin>>ss[1]>>ss[2];
    for (int i=1;i<=6;i++)
    {
        if (s[i].find(ss[1])!=-1) vis[i]=true;
        if (s[i].find(ss[2])!=-1) vis[i]=true;
        if (!vis[i]) Q=i;
    }
    if (n==1) {cout<<"YES"<<endl<<s[Q];return 0;}
    pos=0;
    for (int i=1;i<=6;i++) 
    {
        if (vis[i]) continue;
        sp.clear();sp+=s[i][2],sp+=s[i][0];
        if (sp.find(ss[1])!=-1) continue;
        if (sp.find(ss[2])!=-1) continue;
        pos=i;
    }
    if (pos) 
    {
        printf("YES
");
        for (int i=1;i<=n;i++) cout<<s[pos];
    }
    else 
    {
        printf("YES
");
        for (int i=1;i<=n;i++) cout<<s[Q][0];
        for (int i=1;i<=n;i++) cout<<s[Q][1];
        for (int i=1;i<=n;i++) cout<<s[Q][2];
    }
    return 0;
} 

F. Unstable String Sort

咕咕咕,不会写,题解也看不懂,awcsl。。。。。。

G. Path Queries

好久没写树上启发式合并了,一眼题吧,应该算是

首先对每个m个限制进行考虑,将其按需要的限制排序,之后对于每个边并查集维护

启发式合并掉,答案直接统计即可,最后离散回来,输出即可

#include<bits/stdc++.h>
#define I inline
#define LL long long
using namespace std;
const int N=2e5+7;
LL res;
int sz[N],n,fa[N],m;
LL calc(LL x)
{
    return 1LL*(x)*(x-1)/2LL;
}
I int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int find(int x)
{
    if (fa[x]!=x) return fa[x]=find(fa[x]);
    return fa[x];
}
struct node
{
    LL pos,ans,id;
} t[N];
struct edge
{
    int from,to,dis;
    bool operator <(const edge &x) const
    {
        return dis<x.dis;
    }
} e[N];
bool cmp1(node a,node b)
{
    return a.pos<b.pos;
}
bool cmp2(node a,node b)
{
    return a.id<b.id;
}
void merge(int x,int y)
{
    int fx=find(x),fy=find(y);
    if (sz[fx]>sz[fy]) swap(fx,fy);
    res-=calc(sz[fx]);res-=calc(sz[fy]);
    sz[fy]+=sz[fx];
    res+=calc(sz[fy]);
    fa[fx]=fy;
}
void solve()
{
    int pos=1;
    for (int i=1;i<=m;i++)
    {
        while (e[pos].dis<=t[i].pos&&pos<=n-1)
        {
            merge(e[pos].from,e[pos].to);
            pos++;
        }
        t[i].ans=res;
    }
}
int main()
{
    n=read();m=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read(),z=read();
        e[i].from=x;e[i].to=y;e[i].dis=z;
    }
    for (int i=1;i<=m;i++)
    {
        t[i].pos=read(),t[i].id=i;
    }
    sort(e+1,e+n);sort(t+1,t+m+1,cmp1);
    for (int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
    solve();
    sort(t+1,t+m+1,cmp2);
    for (int i=1;i<=m;i++) printf("%I64d ",t[i].ans);
    return 0;
}

代码纯属原创,如果跟题解思路相同或者代码相同,如本人无瓜,qwq

谁能教教我F怎么写的啊,我太菜了。

慢即是快,细则是能,于小处铸迤逦
原文地址:https://www.cnblogs.com/Hale522520/p/11442237.html