2022.07.15 暑假集训 个人排位赛(十)

2022.07.15 暑假集训 个人排位赛(十)

赛后反省

最后一场了,马马虎虎吧。最后1小时上了个厕所,回来没有继续研究麻烦的做法,反而从简去思考,然后就过题了。不用把题目想得太过复杂的。

Problem A

出处

HDU-4857

题解

拓扑排序+优先队列维护。

首先思考的是优先队列维护头节点,使得每次编号最小的点先出队。但是这样子做是错误的,例如以下的图
$$
6\longrightarrow 3\longrightarrow 1

$$

5 ⟶ 4 ⟶ 2 5\longrightarrow 4\longrightarrow 2 542

如果维护头部的最小去做拓扑排序的话,最后的结果会是542631,很明显这不是最优的,因为1号位排在了最后一位。我们也希望在拓扑链上,即使不是头部,但是头部后的某一点小的点也尽量往前排到。所以我们反过来建边,然后每次都是最大号的点出队。这样子能够保证每次出队的都是号数大的,也是靠后去逃生的。最后编号小的会尽可能在最前面出队了。

代码


// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;


const int N = 30005, M = 100005;
int n, T = 1, m;
priority_queue<int> q;
int in_[N];
vector<int> ve[N];

void ready()
{
    cin >> n >> m;
    ffor(i, 1, n) {
        in_[i] = 0;
        ve[i].clear();
    }
    ffor(i, 1, m) {
        int u, v;
        cin >> u >> v;
        ve[v].push_back(u);
        in_[u]++;
    }
    ffor(i, 1, n) {
        if (!in_[i])
            q.push(i);
    }
}

int ans[N], ansi;

void work()
{
    ansi = n;
    while (q.size()) {
        int u = q.top(); q.pop();
        ans[ansi] = u;
        ansi--;
        for (auto v : ve[u]) {
            in_[v]--;
            if (!in_[v])
                q.push(v);
        }
    }
    ffor(i, 1, n) {
        cout << ans[i];
        if (i < n) cout << ' ';
    }
    cout << '\n';
}

signed main()
{
    IOS;
    cin >> T;
    while (T--) {
        ready();
        work();
    }
    return 0;
}





Problem B

出处

Codeforces-1478B

题解

规律题。

首先,以7为例,先将7的倍数全部记录,7,14,21,28,35,42,49,56,63。看个位数的数字,如果各位数相同,并且大于该倍数,则一定可以组成。例如52,首先会有42的达成,那么我们可以把它变成35+17,也就是把其中一个7加上相差的10,35也能分解出5个7,所以这样子是满足条件的。

另外,最主要的是,如果超过了该个位数的10倍,也是完全可以的!!!因为我可以先用10倍之后再加一些个位数,将剩下的数调整至满足条件,所以也是OK的。例如31,d=2。我们可以用21,将剩下的数调整成10,所以也是满足条件的。

代码


// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;



int n, T = 1, ans;
int dp[10][20];
bool f[10][20];
bool vis[10];

void ready()
{
    ffor(i,1,9){
        ffor(j,1,10)
            dp[i][j]=i*j;
       // ffor(j,1,9) cout<<dp[i][j]<<' ';cout<<'\n';
    }
}


void work()
{
    int d;
    cin>>n>>d;
    ffor(i,1,n){
        bool flag=false;
        int a,b;
        cin>>a;
        if(a>=10*d) flag=true;
        if(a%d==0) flag=true;
        for(int j=1;j<=9;j++){
            int t=j*d;
            if(t>a) break;
            int b=a-t;
            if(b==0 || (b%10==0 || b%d==0)){
                flag=true;
                break;
            }
            while(b){
                if(b%10==d) flag=true;
                b=b/10;
            }
        }
        while(a){
            if(a%10==d) flag=true;
            a=a/10;
        }
        
        if(!flag) cout<<"NO\n";
        else cout<<"YES\n";
    }
}

signed main()
{
	IOS;
    ready();
	cin>>T;
	while (T--) {
		work();
	}
	return 0;
}





Problem D

出处

Codeforces-540E

题解

树状数组求逆序对。

先将已经调换了的数字进行求逆序对,然后再计算没有动过的位置。如果是一个数跑到了他的前面,那么它到原来位置期间没有动过得到数与它匹配都是逆序对。如果这个数是跑到了后面,那么期间不动的数也是它的逆序对。

代码


// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;


const int N=1e6;
int n, T = 1, ans;
map<int,int> mp;
map<int,int> loc;
vector<int> alls;
priority_queue<int, vector<int>, greater<int> > q;
int t[N];
int sum[N];

int lowbite(int x){
    return x&(-x);
}

void add(int x){
    while(x<=alls.size()){
        t[x]++;
        x+=lowbite(x);
    }
    return;
}

int get_sum(int x){
    int res=0;
    while(x){
        res+=t[x];
        x-=lowbite(x);
    }
    return res;
}

void ready()
{
    cin>>n;
    ffor(i,1,n){
        int a,b;
        cin>>a>>b;
        if(mp[a]==0) mp[a]=a;
        if(mp[b]==0) mp[b]=b;
        swap(mp[a],mp[b]);
    }
    int li=0;
    int i=1,las=0;
    for(auto item:mp){
        //if(item.first == item.second) continue;
        q.push(item.second);
        alls.push_back(item.first);
        loc[item.second]=item.first;
        //cout<<item.first<<' '<<item.second<<'\n';

        sum[i]=item.first-las-1;
        sum[i]+=sum[i-1];
        las=item.first;
        i++;
    }
    sort(alls.begin(),alls.end());
}

int find_(int x){
    int res=lower_bound(alls.begin(),alls.end(),x)-alls.begin();
    res++;
    return res;
}

void work()
{
    while(q.size()){
        int u=q.top();q.pop();
        int i=find_(u);
        int now=find_(loc[u]),to=i;
        ans+=get_sum(alls.size())-get_sum(now);
        add(now);
        //ans+=(u-loc[u])-(get_sum(i)-get_sum(loc[u]));
        //add(loc[u]);
    }
    //cout<<ans<<"ans\n";
    int i=1;
    for(auto item:mp){
        if(item.second>item.first){
            ans+=sum[find_(item.second)]-sum[i];
            //cout<<ans<<'\n';
        }
        else{
            ans+=sum[i]-sum[find_(item.second)];
        }
        i++;
    }
    cout<<ans;
}

signed main()
{
	IOS;
	//	cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}





Problem G

出处

Codeforces-588B

题解

先分解出因数出来,然后要求最大的,从最大的因子开始往前查找,看是否是某个数的平方的倍数即可。

题解


// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;



int n, T = 1;
vector<int> ans;

void ready()
{

}



void work()
{
    cin>>n;
    ffor(i,1,sqrt(n)){
        if(n%i==0){
            ans.push_back(i);
            ans.push_back(n/i);
        }
    }
    sort(ans.begin(),ans.end());
    rrep(i,ans.size()-1,0){
        int t=ans[i];
        bool flag=true;
        ffor(j,2,sqrt(t)){
            int jj=j*j;
            if(t%jj==0){
                flag=false;
                break;
            }
        }
        if(flag){
            cout<<t;
            return;
        }
    }
}

signed main()
{
	IOS;
	//	cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: darkbzoj.cc是一个在线的题库和程序设计平台。与其他常见的程序设计平台不同的是,darkbzoj.cc的难度较高,所以它更适合经验更为丰富的用户。平台集成了各种不同难度的编程挑战题目,包括算法、数学、图形、字符串、数据结构等领域,满足不同技能层级的编程爱好者需求。 在darkbzoj.cc的题库中,有许多有趣的题目,涵盖了各种算法和数据结构,如并查集、线段树、动态规划等。此外,该平台还可以服务于程序设计比赛,推广和发展技能水平。 因此,darkbzoj.cc不仅是一个有趣的编程平台,而且也是学习和提高编程技能的理想场所,值得更多编程爱好者的尝试和探索。 ### 回答2: darkbzoj.cc是一个在线编程题库,也可以称为黑暗集训队题库。这个网站的题目大部分都是计算机竞赛的经典题目,难度较高,主要面向ACM/ICPC竞赛选手、OI/NOI选手、算法研究人员以及对算法挑战感兴趣的程序员们。 这个网站包含了很多题目,其中很多都是经典的算法题目,如最短路、最小生成树、网络流、计算几何、字符串算法等。对于那些对这些经典算法感兴趣的人来说,这个网站是一个很好的学习资源。 除此之外,这个网站还提供了一些更加高级的算法题目,需要一些高级的知识来解决。因此,对于对于那些挑战自己的人来说,这个网站也是一个很好的选择。 总之,darkbzoj.cc提供了一个充满挑战的编程题库,为计算机科学专业的学生们以及程序员们提供了一个测试和提高他们编程技能的地方。 ### 回答3: Darkbzoj.cc是一个在线的算法竞赛平台,旨在为全球的程序员提供优秀的学习资源和挑战比赛。通过Darkbzoj.cc,用户可以学习算法、优化程序、提高编程技巧,并在比赛中体验竞技的乐趣。 Darkbzoj.cc提供了丰富的学习资料和编程题目,包括数据结构、算法基础、动态规划、图论以及数论等方面的知识。该平台具有良好的用户体验,界面清晰简洁,让用户更加专注于学习和编程。 此外,Darkbzoj.cc还提供了许多高质量的比赛,并与全球知名的算法竞赛平台进行合作,包括Codeforces、Atcoder、Topcoder等。这些比赛不仅能够提供良好的竞赛体验,还能够激励用户学习和提高自己的编程技能。 总之,Darkbzoj.cc是一个优秀的算法竞赛平台,不仅提供了优质的学习资源和编程题目,还能够为用户提供竞赛切磋的机会,是全球程序员必备的学习和竞赛平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值