• Codeforces Round #686 (Div. 3)


    A. Special Permutation

    题意:

    给出n,要求输出一个1到n的全排列,需要满足(a_i ot=i)

    思路:

    直接输出2到n,最后输出1即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    int t,n;
    int main(){
        cin>>t;
        while(t--){
            cin >> n;
            for(int i=2;i<=n;i++){
                cout<<i<<' ';
            }
            cout << 1;
            cout<<endl;
        }
        return 0;
    }
    

    B. Unique Bid Auction

    题意:

    给出一个数组,要求输出所有只出现过一次的数中最小的数

    思路:

    直接求即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    int t, n,a[N];
    int main(){
        cin >> t;
        while(t--){
            cin>>n;
            map<int, int> mp;
            for (int i = 1; i <= n;i++){
                cin >> a[i];
                mp[a[i]]++;
            }
            int res = 0x3f3f3f3f;
            int pos = 0;
            for (int i = 1; i <= n;i++){
                if(mp[a[i]]==1){
                    if(res>a[i]){
                        res = a[i];
                        pos = i;
                    }
                }
            }
            if(res==0x3f3f3f3f){
                cout << -1 << endl;
            }
            else{
                cout << pos << endl;
            }
        }
        return 0;
    }
    

    C. Sequence Transformation

    题意:

    给出一个数组,只能选择一个数字x,然后每次都要消一个[L,R],[L,R]中不能包含x

    问使得数列全相等的最少操作数

    思路:

    模拟题,读入的时候直接判断(a_i)(a_{i-1})是否相同以及是否是第一次出现,然后将对应的答案加一即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    int t,n,a[N];
    
    int main(){
        cin>>t;
        while(t--){
            cin>>n;
            map<int ,int >mp;
            for(int i=1;i<=n;i++){
                cin>>a[i];
                if(i!=1){
                    if(a[i]!=a[i-1]){
                        if(mp[a[i]]==0)
                        mp[a[i]]++;
                        mp[a[i - 1]]++;
                    }
                }
            }
            int res=0x3f3f3f3f;
            for(int i=1;i<=n;i++){
                res=min(res,mp[a[i]]);
            }
            cout<<res<<endl;
        }
        return 0;
    }
    

    D. Number into Sequence

    题意:

    给出n,要求输出最长的一组数,满足它们的乘积能被n整除。而且(a_i)能够整除(a_{i-1})

    思路:

    质因子分解,找出出现次数x最多的质因子,先输出前x-1个,最后乘上其他因数的乘积输出。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e7 + 10;
    int n, m, T;
    int prime[N], cnt;
    int st[N];
    long long sum = 0, res_val = 0,t,x;
    
    void get_prime(int n) {
        for (int i = 2; i <= n; ++i) {
            if (!st[i]) prime[cnt++] = i; // 如果这个数字没有被记录,那么这个数字必然为素数,记录一下
            for (int j = 0; prime[j] <= n/i; ++j) {
                st[prime[j] * i] = true;  // 筛掉pj*i这个合数
                if (i % prime[j] == 0)  break; // i%pj==0,说明pj是i的最小素因子,因此i*素数的最小素因子也是pj,在i递增的时候也会被筛掉,因此不需要在这里判断
            }                
        }
    }
    
    long long  qmi(long long a, long long k) {
        long long res = 1 ;  // res记录答案, 模上p是为了防止k为0,p为1的特殊情况
        while(k) {  // 只要还有剩下位数
            if (k & 1) res = (long long)res * a ;  // 判断最后一位是否为1,如果为1就乘上a,模上p, 乘法时可能爆int,所以变成long long
            k >>= 1;  // 右移一位
            a = (long long) a * a ;  // 当前a等于上一次的a平方,取模,平方时可能爆int,所以变成long long
        }
        return res;
    }
    
    
    int main() {
        get_prime(N - 1);
        cin >> T;
        while(T--) {
            scanf("%lld", &x);
            t = x;
            sum = 0, res_val = 0;
            for (int i = 0; prime[i] <= x / prime[i]; ++i) {
                int p = prime[i];
                if (x % p == 0) {
                    int s = 0;
                    while (x % p == 0) {
                        s++;
                        x /= p;
                    }
                    if ((long long)s > sum) {
                        sum = (long long)s;
                        res_val = p;
                    }
                }
            }
            if (x > 1) {
                if ((long long)1 > sum) {
                    sum = 1;
                    res_val = x;
                }
            }
            cout << sum << endl;
            if (sum == 1) 
            printf("%lld
    ", t);
            else 
            {
                for (int i = 1; i <= sum - 1; ++i) printf("%lld ", res_val);
                printf("%lld
    ", (t / qmi(res_val, sum - 1)));
            }
            
        }
        return 0;
    }
    
    

    E. Number of Simple Paths

    大意:

    给出一个n个点n条边的无向图,问从任意一个点走到其他任意一个点,有多少路径,需要注意的是1->2->3与3->2->1视为相同的路径

    思路:

    n个点n条边的无向图,被称为基环图,它可以看做一个基环再向外延伸出几个树的结构,如下图:

    DhwzuV.png

    对于同一个树上的两个点,只有1条路径,所以每个树提供了(C_{num}^{2})个路径(num为这棵树的节点数),而对于不在同一个树上的两个点,因为需要经过基环,所以就存在从两种经过环的方式,所以为2条路径,所以我们可以先按照每对点都有2条路径来做,然后删掉每棵树提供的路径即可。

    怎么找环呢?利用拓扑排序,没有被遍历到的节点就一定在环上。最后再对环上的每个节点(即每棵树的根节点)进行一遍dfs找出这棵树的节点数即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 5;
    typedef long long LL;
    int t, n,du[N],istree[N],num[N];
    vector<int> mp[N];
    
    void dfs1(int now,int fa){
        for (int i = 0; i < mp[now].size();i++){
            int next = mp[now][i];
            if(next==fa){
                continue;
            }
            du[next]--;
            du[now]--;
            if(du[next]==1){
                istree[next] = 1;
                dfs1(next, now);
            }
        }
    }
    
    int dfs2(int now,int fa){
        num[now] = 1;
        for (int i = 0; i < mp[now].size();i++){
            int next = mp[now][i];
            if(next==fa)
                continue;
            if(istree[next]){
                num[now] += dfs2(next, now);
            }
        }
        return num[now];
    }
    
    int main(){
        cin >> t;
        while(t--){
            cin >> n;
            for (int i = 1; i <= n;i++){
                mp[i].clear();
                istree[i] = 0;
                du[i] = 0;
            }
            for (int i = 1; i <= n ;i++){
                int x, y;
                cin >> x >> y;
                mp[x].push_back(y);
                mp[y].push_back(x);
                du[x]++;
                du[y]++;
            }
            for (int i = 1; i <= n;i++){
                if(du[i]==1){
                    istree[i] = 1;
                    dfs1(i,0);   //找环
                }
            }
            LL res = n * ((LL)n - 1);
            for (int i = 1; i <= n;i++){
                if(istree[i]==0){
                    dfs2(i, 0);   //找树
                    res-=num[i] * ((LL)num[i]  - 1)/2;
                }
            }
            cout << res << endl;
        }
        return 0;
    }
    

    F. Array Partition

    大意:

    给出一个数组,要求将这个数组分成长度分别为x,y,z(均不为0)的三部分,使得中间一部分的数组最小值等于前后两部分数组的最大值,即:(max(1, x) = min(x + 1, x + y) = max(x + y + 1, n))

    思路:

    首先单调栈维护每个位置上的数所控制的左右端点,直接找出现次数大于等于3的数,然后判断这个数第一次出现的位置能否控制到最左边,最后出现的位置能否控制最右边,如果能就枚举中间出现的位置,看控制的区间是否有交集即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 5;
    typedef long long LL;
    int t, n,a[N],maxl[N],maxr[N],minl[N],minr[N];
    int main(){
        cin >> t;
        while(t--){
            cin >> n;
            stack<int> st;
            for (int i = 1; i <= n;i++){
                scanf("%d", &a[i]);
            }
            for (int i = 1; i <= n;i++){
                while(!st.empty()&&a[st.top()]>=a[i]){   //求以a[i]为最小值的左区间
                    st.pop();
                }
                if(st.empty()){
                    minl[i] = 0;
                }
                else{
                    minl[i] = st.top();
                }
                st.push(i);
            }
            while(!st.empty()){
                st.pop();
            }
            for (int i = n; i >= 1;i--){
                while(!st.empty()&&a[st.top()]>=a[i]){   //求以a[i]为最小值的右区间
                    st.pop();
                }
                if(st.empty()){
                    minr[i] = n+1;
                }
                else{
                    minr[i] = st.top();
                }
                st.push(i);
            }
            while(!st.empty()){
                st.pop();
            }
            for (int i = 1; i <= n;i++){
                while(!st.empty()&&a[st.top()]<=a[i]){   //求以a[i]为最大值的左区间
                    st.pop();
                }
                if(st.empty()){
                    maxl[i] = 0;
                }
                else{
                    maxl[i] = st.top();
                }
                st.push(i);
            }
            while(!st.empty()){
                st.pop();
            }
            for (int i = n; i >= 1;i--){
                while(!st.empty()&&a[st.top()]<=a[i]){   //求以a[i]为最大值的右区间
                    st.pop();
                }
                if(st.empty()){
                    maxr[i] = n+1;
                }
                else{
                    maxr[i] = st.top();
                }
                st.push(i);
            }
            unordered_map<int, vector<int> > mp;
            unordered_map<int, int> no;
            for (int i = 1; i <= n;i++){
                mp[a[i]].push_back(i);
                no[a[i]] = 0;
            }
            int flag = 0;
            for (int i = 1; i <= n;i++){
                if(flag)
                    break;
                if(mp[a[i]].size()<3){
                    continue;
                }
                if(no[a[i]]==1){
                    continue;
                }
                int st = mp[a[i]][0], en = mp[a[i]][mp[a[i]].size()-1];
                if(maxl[st]==0&&maxr[en]==n+1){
                    for (int j = 1; j < mp[a[i]].size() - 1;j++){
                        int mid = mp[a[i]][j];
                        
                        if(minl[mid]+1<=maxr[st]&&minr[mid]-1>=maxl[en]){
                            flag = 1;
                            printf("YES
    ");
                            int x = min(maxr[st]-1, mid-1);
                            int y = max(mid + 1, maxl[en]+1);
                            printf("%d %d %d
    ", x, y - x - 1, n - y + 1);
                            break;
                        }
                    }
                }
                if(flag==0)
                    no[a[i]] = 1;
            }
            if(flag==0){
                printf("NO
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    python3之微信文章爬虫
    selenium不提供修改请求headers、获取响应headers的功能
    dos/bat/cmd相关知识的三个层面
    python处理xml的常用包(lib.xml、ElementTree、lxml)
    python列表操作总结
    从哪些层面评价编程语言
    Windows环境下python多版本配置方案
    一个urllib2构建的html下载器的代理组件的实现方案
    python-selenium实现的简易下载器,并常见错误解决
    python环境配置selenium与IE、Chrome、Firefox、PhantomJS
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14072003.html
Copyright © 2020-2023  润新知