训练集--训练赛8

ps:

以后训练赛不打日期了,因为现在中间穿插了dp/kmp等要学的东西,每天训练也不只是训练赛,日期没啥意义,我扳扳手指头也麻烦.题目不是特别好的也就贴个代码说下题意了,毕竟大部分精力要学新东西.

k-Factorization

Given a positive integer n, find k integers (not necessary distinct) such that all these integers are strictly greater than 1, and their product is equal to n.
分解n到k个数,这些数字乘积为n,稍微有些东西特判下

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n,i,a[21],k,p=1,x;
    bool b=0;
    cin>>n>>k;
    x=k;
    k--;
    while(k>=1) {
        b=0;
        for(i=2; i<n; i++) {
            if(n%i==0) {
                k=k-1;
                a[p]=i;
                p++;
                n=n/i;
                b=1;
                break;
            }
        }
        if(b==0) {
            cout<<-1;
            return 0;
        }
    }
    if(n<2) {
        cout<<-1;
        return 0;
    }
    for(i=1; i<=x-1; i++)
        cout<<a[i]<<" ";
    cout<<n;
}

Odd sum

You are given sequence a1, a2, …, an of integer numbers of length n. Your task is to find such subsequence that its sum is odd and maximum among all such subsequences. It’s guaranteed that given sequence contains subsequence with odd sum.

Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.

You should write a program which finds sum of the best subsequence.
算最大和
稍微注意点负数排序,负数从最大开始取

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n,i,a[100010],z[100010],f[100010],p1=0,p2=0,maxn=0,minx=0,max2=0;
    //freopen("out.txt","r",stdin);
    cin>>n;
    for(i=1;i<=n;i++)
     {scanf("%d",&a[i]);
      if(a[i]>0)
       {z[p1]=a[i];
        p1++;
        maxn=maxn+a[i];
       }
      else if(a[i]<0)
       {f[p2]=a[i];
        p2++;
         }  
     }//cout<<maxn;
     if(maxn&1)
     {cout<<maxn;return 0;
     }
     sort(z,z+p1);
     sort(f,f+p2);//cout<<f[1];
    for(i=0;i<p1;i++)
     if(z[i]&1)
     {minx=z[i];break;
     }
    for(i=p2-1;i>=0;i--)
     {if(abs(f[i])%2==1)
     {max2=f[i];break;
     }
     }
    if(minx%2==0&&max2&1)
    cout<<maxn+max2;
    else if(max2%2==0&&minx&1)
    cout<<maxn-minx;
    else if(minx&1&&max2&1)
     cout<<max(maxn+max2,maxn-minx)<<endl;
    return 0;
}

Minimal string

Petya recieved a gift of a string s with length up to 105 characters for his birthday. He took two more empty strings t and u and decided to play a game. This game has two possible moves:

Extract the first character of s and append t with this character.
Extract the last character of t and append u with this character.
Petya wants to get strings s and t empty and string u lexicographically minimal.

You should write a program that will help Petya win the game.
不错的题,字符串题目,先将一个给定字符串从先到后放到一个暂存的空串中,在每一个时刻,都可以将暂存的串中末尾的字符放到答案字符串,要求输出最小字典序的答案字符串.
用栈可轻松解决.从后到前存下每个字符及它后面最小的,然后从前到后遍历,判断压栈出栈.

#include<bits/stdc++.h>
using namespace std;
int main() {
    string s;
    int i;
    stack<char> c;
    //queue<char> q;
    int a[100010];
    memset(a,-1,sizeof(a));
    cin>>s;
    for(i=s.size()-1; i>=0; i--) {
        if(i==s.size()-1)a[i]=s[i]-'a';
        else a[i]=min(a[i+1],s[i]-'a');
    }

    for(i=0; i<s.size(); i++) {
        if(i==0)
            c.push(s[i]);
        else {
            for(int j=c.size(); j>=1; j--) {
                if(c.top()-'a'<=a[i]) {
                    cout<<c.top();
                    c.pop();
                } else break;
            }
            c.push(s[i]);
        }
    }
    while(!c.empty()) {
        printf("%c",c.top());
        c.pop();
    }
    printf("\n");
    return 0;
}

Broken BST

Let T be arbitrary binary tree — tree, every vertex of which has no more than two children. Given tree is rooted, so there exists only one vertex which doesn’t have a parent — it’s the root of a tree. Every vertex has an integer number written on it. Following algorithm is run on every value from the tree T:

Set pointer to the root of a tree.
Return success if the value in the current vertex is equal to the number you are looking for
Go to the left child of the vertex if the value in the current vertex is greater than the number you are looking for
Go to the right child of the vertex if the value in the current vertex is less than the number you are looking for
Return fail if you try to go to the vertex that doesn’t exist
Here is the pseudo-code of the described algorithm:

bool find(TreeNode t, int x) {
if (t == null)
return false;
if (t.value == x)
return true;
if (x < t.value)
return find(t.left, x);
else
return find(t.right, x);
}
find(root, x);
The described algorithm works correctly if the tree is binary search tree (i.e. for each node the values of left subtree are less than the value in the node, the values of right subtree are greater than the value in the node). But it can return invalid result if tree is not a binary search tree.

Since the given tree is not necessarily a binary search tree, not all numbers can be found this way. Your task is to calculate, how many times the search will fail being running on every value from the tree.

If the tree has multiple vertices with the same values on them then you should run algorithm on every one of them separately.
将一棵树按二叉搜索树的方法搜索,搜完输出失败次数.
直接暴力会gg,因此要从根节点遍历一遍,判断每个能找不找得到,需要注意相同的数字只要一个只能找到其余也都要算可以..(坑)

#include<bits/stdc++.h>
#define ll long long
#define N 100010
using namespace std;
struct gg{
    int left,right,x,parent,flag;
} t[N];
int inf=1e10;

void dfs(int x,int k,int ma,int mn)
{
        if(x==-1)return;
        if(k>=mn&&k<=ma)t[x].flag=1;
        dfs(t[x].left,t[t[x].left].x,min(ma,t[x].x),mn);
        dfs(t[x].right,t[t[x].right].x,ma,max(mn,t[x].x));}

bool cmp(gg a, gg b)
{return a.x<b.x;
}

int main() {
    int i,n,top=1,cnt=0,ans=0;bool iffnd=0;
    //freopen("in.txt","r",stdin);
    cin>>n;
    for(i=1; i<=n; i++) {
        scanf("%d%d%d",&t[i].x,&t[i].left,&t[i].right);
        t[t[i].left].parent=i;
        t[t[i].right].parent=i;
    } 
    while(t[top].parent)                      
    {top=t[top].parent;
    }
    dfs(top,t[top].x,inf,-999999);
    sort(t+1,t+n+1,cmp);
    ans=n;
    t[n+1].x=-1;
    for(i=1;i<=n+1;i++)
    {if(i>=2&&t[i].x!=t[i-1].x)
      {if(iffnd==1)ans-=cnt;cnt=0;iffnd=0;
      }
     if(t[i].flag==1)iffnd=1;
     cnt++;
     //cout<<t[i].flag<<" "<<t[i].x<<" "<<cnt<<" "<<ans<<endl;
    }
    cout<<ans;
}

Array Queries

a is an array of n positive integers, all of which are not greater than n.

You have to process q queries to this array. Each query is represented by two numbers p and k. Several operations are performed in each query; each operation changes p to p + ap + k. There operations are applied until p becomes greater than n. The answer to the query is the number of performed operations.
类似于动规题目,一个数组,可以将p改为p+ap+k,问当它比n大最小次数,暴力超时,因此,先在输入时处理一些小的答案.

#include<bits/stdc++.h>
using namespace std;//·½·¨£ºdp.
int n,a[100010]= {0},ans[100010][340]={0};
int main() {
    int i,j,q,p,m,k;
    cin>>n;
    for(i=1; i<=n; i++)
        scanf("%d",&a[i]);
    cin>>q;
    for(i=1;i<=320;i++)
     for(j=n;j>=1;j--)
     {if(i+j+a[j]>n)ans[j][i]=1;
       else ans[j][i]=ans[j+a[j]+i][i]+1;
     }
    for(i=1; i<=q; i++) {
        int ans1=0;
        scanf("%d%d",&p,&k);
        if(k<=320)cout<<ans[p][k]<<endl;
        else 
         {while(p<=n)
          {p+=a[p]+k;
          ans1++;
          }
          cout<<ans1<<endl;
         }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值