【浮*光】【Educational Codeforces Round 46】A,B,C,D

嘿嘿嘿这个是1000哦 O(∩_∩)O~~

A. Codehorses T-shirts

#include <bits/stdc++.h>
using namespace std;

/*【A】给出n个上一年的衣服码数和n个今年的衣服码数,
问最少修改多少次字母把上一年的衣服码数变成今年的衣服码数  */

const int m = 123;
int siz1[109],siz2[109];
bool okk[109];

int main(){
    int n,len=1,ans=0; cin>>n;
    char ss[109],s2[109];
    for(int i=1;i<=n;i++){ 
        cin>>ss; int cnt=0;
        for(int j=0;j<strlen(ss);j++)
            cnt=m*cnt+ss[j]-'A'; //哈希值
        siz1[len]=cnt; len++;
    }
    int len2=1;
    for(int i=1;i<=n;i++){
        cin>>s2; int cnt=0;
        for(int j=0;j<strlen(s2);j++)
            cnt=m*cnt+s2[j]-'A';  
        siz2[len2]=cnt; len2++;
    }
    memset(okk,false,sizeof(okk));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(siz2[j]==siz1[i]){
                siz2[j]=-1; //这个地方注意:不能重复配对
                okk[i]=true; break;
            }
    for(int i=1;i<=n;i++)
        if(!okk[i]) ans++;
    printf("%d\n",ans);
}

B. Light It Up

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【B.Light It Up】
给出n个节目时间,每个时间点灯都会改变开关状态,
问插入一个任意时刻的节目后,亮灯时间最长为多长。
输入:节目数n,总时长m,n个节目的时间。 */

/*【分析】将n个数据转化为 a1-0,a2-a1,a3-a2 ...... m-an 共n+1个数。
将这n+1个数中,某个大于1的数分解为两个大于等于1的数,或者选择不分解。
而灯亮时间其实就是下标为偶数的数的和,然而某个数分解为两个数、
会导致这个数{后面部分}原来是偶数的变成奇数,选择次序完全相反。
》》先转化好n+1个数存进a数组,建立all数组,b数组,
叠加法求出第i个下标位置时{a0到ai的总和},以及{i位置和它之前的灯亮时间总和}
为了考虑到不做变化的情况,max ans初值为n+1个数的灯亮时间总和,
    maxans=std::max(maxans,b[i]-1+all[n]-all[i]-b[n]+b[i]); //不断更新ans
↑↑↑ 被分解的数下标无论是奇是偶,奇数分解为1,x-1,偶数分解为x-1,1。
故而前i个数包括第i个本身的灯亮时间为b[i]-1,而(all[n]-all[i]-(b[n]-b[i]),
表示i后方奇偶顺序恰好相反,求出反答案。加和即为总答案。 */

const int maxn=100005;
ll a[maxn],b[maxn],all[maxn]; //a[i]用于记录每个时间差
//b[i]即是i位置和它之前的灯亮时间总和(无论奇偶)
 
int main(){
    int n,m; scanf("%d%d",&n,&m);
    ll t1=0,t2,sum=0;
    for(int i=0;i<n;i++){
        cin>>t2;
        a[i]=t2-t1; t1=t2;
    }
    a[n]=m-t2; //最后一个时间间隔
    for(int i=0;i<=n;i++){
        if(i%2==0) sum+=a[i];
        all[i]=all[i-1]+a[i];
        b[i]=sum; //求b[i],all[i]
    }
    ll maxans=sum;
    for(int i=0;i<=n;i++)
        maxans=max(maxans,b[i]-1+all[n]-all[i]-b[n]+b[i]);
    cout<<maxans<<endl;
    return 0;
}
//来自 https://blog.csdn.net/qq_31964727/article/details/80837110 
//炒鸡喜欢这个dalao(*ο*)炒鸡聪明、代码风格很喜欢、而且讲解炒鸡清楚^~^

C. Covered Points Count
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【C. Covered Points Count】
给出n个线段,问覆盖i次的点有多少个。每个i对应的值按1~n顺序输出。 */

/*【分析】不用逐个点判断,因为所有的点被这n条线段的2*n个端点切割成了许多段,
而每一段内的经过的线的条数在这个小段内是相同的,
》》将所有线段的端点排序,将这线段a上点的数目加到对应的答案线段数目里。
因为多线段端点可能重复,最好等到新端点开始计算时再计算老端点,此时不用担心重复。*/

const int maxn=100005;
pair<ll,int> a[500019];
ll num[500019];

int main(){
    int n; scanf("%d",&n);
    ll lef,rigt; //左右端点
    for(int i=0;i<n;i++){
        cin>>lef>>rigt;
        a[2*i]=make_pair(lef,0); //second为0表示为线段起点,1表示终点 
        a[2*i+1]=make_pair(rigt,1);
    } 
    sort(a,a+2*n); //默认按照first的大小排序
    
    ll now=0,lastpos=-1,temp=0;
    //now表示当前经过此端点的线段条数
    //lastpos表示上一个端点的位置
    //temp表示上一个端点上被删除的线段终点数目 
    
    for(int i=0;i<2*n;i++) num[i]=0; //初始化 出现i次的线段数目
    for(int i=0;i<2*n;i++){
        if(a[i].first>lastpos){ //新点接入,统计之前的答案
            num[now+temp]++,temp=0;   //前一个端点 
            num[now]+=a[i].first-lastpos-1; //此端点到前一个端点间线段上的点 
            lastpos=a[i].first;
        }
        if(a[i].second){ temp++; now--; }
        else now++;  
    }
    num[now+temp]++; //最后一个端点的收尾
    for(int i=1;i<=n;i++) cout<<num[i]<<" "; 
    return 0;
}

D. Yet Another Problem On a Subsequence

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【D. Yet Another Problem On a Subsequence】
一个数组为好数组、当且仅当这个数组有k个元素且首元素为k-1,
一个序列为好序列、当且仅当这个序列可以分为几个好数组。
在给定序列中,可以找到多少子序列,满足它是好序列。 */

//因为关键在于区间的第一个,我们从后向前考虑,dp[i]表示以i为开头。
//sum[i]表示i后面可能的情况数量。对于i:还要取a[i]个。
//我们假设最后一个数在j位置,那么dp[i]+=C(j-i-1,a[i]-1)*(1+sum[j+1]);
//复杂度为O(N^2);

const int Mod=998244353;
const int maxn=1010;
int a[maxn],dp[maxn],sum[maxn];
int c[maxn][maxn],ans;

int main(){
    int N,i,j; scanf("%d",&N);
    for(i=0;i<=N;i++)  c[i][0]=1,c[i][1]=i,c[i][i]=1;
    for(i=1;i<=N;i++)
     for(j=1;j<=N;j++)
       c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
    for(i=1;i<=N;i++) scanf("%d",&a[i]); 
    for(i=N;i>=1;i--){
        if(a[i]>0&&i+a[i]<=N){
            for(j=i+a[i];j<=N;j++){
                (dp[i]+=(ll)c[j-i-1][a[i]-1]*(1+sum[j+1])%Mod)%=Mod;
            }
        }
        sum[i]=(sum[i+1]+dp[i])%Mod;
    }
    printf("%d\n",sum[1]);
    return 0;
} // 来自http://www.cnblogs.com/hua-dong/p/9238795.html 感谢dalao


                                                                                ——时间划过风的轨迹,那个少年,还在等你。

猜你喜欢

转载自blog.csdn.net/flora715/article/details/80981836