Educational Codeforces Round 75 (Rated for Div. 2)

(体验到了胡出一道题但是写锅的绝望呢)

A:

送分题。

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
bool may[30]; char str[maxn];

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

int main(){
    int T=read();
    while(T--){
        scanf("%s",str+1);
        int n=strlen(str+1);
        memset(may,0,sizeof(may));
        for(int i=1;i<=n;){
            int j=i; while(str[j]==str[j+1]) j++;
            if((j-i+1)%2) may[str[i]-‘a‘]=1;
            i=j+1;
        }
        for(int i=0;i<26;i++)
            if(may[i]) printf("%c",(char)(i+‘a‘));
        cout<<endl;
    }
    return 0;
}

A

B:

送分题。因为根据样例猜结论wa了一发。

看到有人dp???这难道不是瓶颈在读入的结论题?

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
char str[maxn];

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

int main(){
    int T=read();
    while(T--){
        int n=read(),n1=0,n0=0,t1=0;
        for(int i=1;i<=n;i++){
            scanf("%s",str+1);
            int len=strlen(str+1);
            if(len%2) t1++;
            for(int j=1;j<=len;j++){
                if(str[j]==‘1‘) n1++;
                else n0++;
            }
        }
        if(n0<n1) swap(n0,n1);
        if(t1%2){
            if(n0%2==n1%2) cout<<n-1<<endl;
            else cout<<n<<endl;
        }
        else if(t1==0){
            if(n0%2==1) cout<<n-1<<endl;
            else cout<<n<<endl;
        }
        else cout<<n<<endl;
    }
    return 0;
}

B

C:

送分题。

注意到奇数之间的顺序不会变化,偶数之间的顺序也不会变化,于是做一下归并排序的合并操作即可。

#include<bits/stdc++.h>
#define maxn 300005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
char str[maxn];
int t1[maxn],t0[maxn];

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

int main(){
    int T=read();
    while(T--){
        scanf("%s",str+1);
        int n=strlen(str+1);
        t1[0]=t0[0]=0;
        for(int i=1;i<=n;i++){
            if((str[i]-‘0‘)%2) t1[++t1[0]]=str[i]-‘0‘;
            else t0[++t0[0]]=str[i]-‘0‘;
        }
        int p1=1,p0=1;
        while(p1<=t1[0] || p0<=t0[0]){
            if(p1>t1[0]) printf("%d",t0[p0]),p0++;
            else if(p0>t0[0]) printf("%d",t1[p1]),p1++;
            else{
                if(t1[p1]<t0[p0]) printf("%d",t1[p1]),p1++;
                else printf("%d",t0[p0]),p0++;
            }
        }
        cout<<endl;
    }
    return 0;
}

C

D:

送分题。

中位数没有太多性质,要么枚举答案要么二分答案。

二分完判一下边界求能达到目标的最小价值即可。

由于没判一个人wa了一发,边界没判好又wa了一发。

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
ll n; struct node{ll l,r;}a1[maxn],a2[maxn],e[maxn];

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

inline bool cmp1(node x,node y){return x.r<y.r;}
inline bool cmp2(node x,node y){return x.l<y.l;}

inline ll calc(ll x){
    ll sum=0,n1=0,n2=0;
    for(ll i=1;i<=n;i++)
        if(e[i].r<x) sum+=e[i].l,n1++;
    for(ll i=1;i<=n;i++)
        if(e[i].l>x) sum+=e[i].l,n2++;
    if(n1>n/2) return (1ll<<60);
    if(n2>n/2) return 0;
    ll tp=n/2-n1;
    for(ll i=1;i<=n;i++)
        if(a1[i].l<=x && a1[i].r>=x){
            if(tp) sum+=a1[i].l,tp--;
            else sum+=x;
        }
    return sum;
}

int main(){
    ll T=read();
    while(T--){
        n=read(); ll s=read();
        for(ll i=1;i<=n;i++){
            e[i].l=a1[i].l=a2[i].l=read();
            e[i].r=a1[i].r=a2[i].r=read();
        }
        sort(a1+1,a1+n+1,cmp2);
        if(n==1){cout<<min(s,e[1].r)<<endl;continue;}
        ll l=1,r=(ll)(1e9),ans=0;
        while(l<=r){
            ll mid=l+r>>1;
            //cout<<mid<<":"<<calc(mid)<<endl;
            if(calc(mid)<=s) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

D

E:

送分题。但我把分还给了这个世界。

实际上所有人被m值划分成了若干个阶梯,每个阶梯都会在一起投票。

考虑$m_{i}$最大的那个人。如果他前面的人数还不到$m_{i}$,那不管怎么样都必须花钱买他,否则暂时没有必要买他。

那么按m值排序后倒着考虑每个人,维护一个以$p_{i}$为关键字的小根堆,如果要买就买若干个最小的。

容易用归纳法证明该算法的正确性。复杂度$O(nlogn)$。

(当时是0:40,我在大脑混乱的情况下想写一个给数组直接排序的$O(n^{2}logn)$的做法过E1。)

(然后我没考虑如果给后面的东西按p排序会把有序的m搞乱掉,于是我就对着一发wa on 2沉思到考试结束。)

(这种明显是我的锅当然要甩给石神了!谁让它那么可爱!)

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
ll n;
struct node{ll m,p,id;}a[maxn];
priority_queue<ll> q;

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

inline bool cmp1(node x,node y){return x.m<y.m;}
inline bool cmp2(node x,node y){return x.p<y.p;}

int main(){
    ll T=read();
    while(T--){
        n=read();
        for(ll i=1;i<=n;i++) a[i].m=read(),a[i].p=read();
        sort(a+1,a+1+n,cmp1);
        ll num=0,ans=0;
        for(ll i=n;i>=1;i--){
            q.push(-a[i].p);
            while(i-1+num<a[i].m) ans+=-q.top(),q.pop(),num++;
        }
        printf("%I64d\n",ans);
        while(!q.empty()) q.pop();
    }
    return 0;
}

E

F:

注意到对于一个红块,它可选的白块范围是确定的。

对于一个$Q_{i}$,如果我们确定了放哪个红块,那么能放的白块数就确定下来了。

那么我们可以预处理每个红块对应的放$i$个白块的方案数。

推组合数复杂度显然不对,但可以考虑生成函数,它的本质也是解决有限或无限元素的组合问题。

如果一个白块的$h_{i}$出现了多于两次,由于要求严格递增,那么它最多只能在两边各放一个。于是我们可以把它当做出现了两次。

根据生成函数相关知识,我们得到:

1.若一个$h_{i}$出现一次,那么它在方案中对应一个$(1+2x)$,表示不放/放左边或放右边。

2.若一个$h_{i}$出现两次,那么它在方案中对应一个$(1+2x+x^{2})$,表示不放/放左边或放右边/放两边。

将这些多项式卷起来,$x^{m}$项的系数就是放m个白块的方案数。

一开始我写了一个卷积快速幂进行$logn$次$NTT$。然后T on 97。(幸好我考场上压根没写)

然后在欧神的教导下我发现:进行一次$NTT$后做点值快速幂就完事了,我根本没学明白。

一些非常致命的细节:

1.写多项式应用题时一定要开一个临时数组然后对其$NTT$,不然会将原数组变换成点值表示。

2.如果你不想开临时数组可以每次把用到的数组清空一遍,注意清空一定要清到$NTT$时的len而不是需要保留的len。

3.强烈不建议$NTT$过去后再$NTT$回来,1s跑不了几次$NTT$。

4.当你把一个数组作为参数传到函数里时是用不了$sizeof(a)$的,这时候这东西只会返回1个变量的$size$。

#include<bits/stdc++.h>
#define maxn 300005
#define maxm 1<<21|1
#define inf 0x7fffffff
#define mod 998244353
#define g 3
#define ll long long
#define rint register ll

using namespace std;
ll mx=3e5,h1[maxn],h2[maxn],ind[maxm];
ll p1[maxm],p2[maxm],tq[maxm],tp[maxm];
ll res[5][maxm];

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

inline ll mo(ll x){return x>=mod?x-mod:x;}
inline ll power(ll a,ll b){ll ans=1;while(b){ans=(b&1)?ans*a%mod:ans,a=a*a%mod,b>>=1;}return ans;}
inline void copy(ll *a,ll *b){for(rint i=0;i<(maxm>>1);i++) a[i]=b[i];}
inline void clear(ll *a,ll x){for(rint i=0;i<(maxm>>1);i++) a[i]=0;a[0]=1,a[1]=(x?2:0),a[2]=(x==2);} //不能使用sizeof(*a)的形式
inline void print(ll *a){for(rint i=0;i<=10;i++) cout<<a[i]<<" ";cout<<endl;}

namespace P{
    inline void ntt(ll *a,ll n,ll op){
        for(rint i=0;i<n;i++) ind[i]=(i&1)?((ind[i>>1]>>1)|(n>>1)):(ind[i>>1]>>1);
        for(rint i=0;i<n;i++) if(ind[i]>i) swap(a[i],a[ind[i]]);
        for(rint l=2;l<=n;l<<=1){
            ll p=power(g,(mod-1)/l);
            if(op==-1) p=power(p,mod-2);
            for(rint i=0;i<n;i+=l)
                for(ll j=i,w=1,t;j<i+(l>>1);j++,w=w*p%mod)
                    t=a[j+(l>>1)]*w%mod,a[j+(l>>1)]=mo(a[j]-t+mod),a[j]=mo(a[j]+t);
        }
    }
    inline ll conv(ll *a,ll n,ll *b,ll m){
        ll len=1,lim=min(n+m,mx);
        while(len<=lim) len<<=1;
        ntt(a,len,1),ntt(b,len,1);
        for(rint i=0;i<len;i++) a[i]=a[i]*b[i]%mod;
        ntt(a,len,-1); ll inv=power(len,mod-2);
        for(rint i=0;i<len;i++) a[i]=a[i]*inv%mod;
        return lim;
    }
    inline ll conp(ll *a,ll b,ll c){
        if(b==0){clear(a,0);return 0;}
        ll len=1,lim=min(c*b,(ll)mx);
        while(len<=lim) len<<=1; ntt(a,len,1);
        for(rint i=0;i<len;i++) a[i]=power(a[i],b);
        ntt(a,len,-1); ll inv=power(len,mod-2);
        for(rint i=0;i<len;i++) a[i]=a[i]*inv%mod;
        return lim;
    }
}

int main(){
    ll n=read(),k=read();
    for(rint i=1;i<=n;i++) h1[i]=read();
    for(rint i=0;i<k;i++) h2[i]=read();
    sort(h1+1,h1+1+n),sort(h2,h2+k);
    for(rint i=0;i<k;i++){
        ll l1=0,l2=0,now=1,n1=0,n2=0;
        while(now<=n){
            if(h1[now]>=h2[i]) break;
            ll j=now; while(j+1<=n && h1[j]==h1[j+1]) j++;
            if(j==now) n1++; else n2++; now=j+1;
        }
        clear(p1,1),l1=1;l1=P::conp(p1,n1,l1);
        clear(p2,2),l2=2;l2=P::conp(p2,n2,l2);
        //print(p1),print(p2);
        l1=P::conv(p1,l1,p2,l2),copy(res[i],p1);
        //print(res[i]);
    }
    ll Q=read();
    while(Q--){
        ll q=read(),ans=0;
        for(rint i=0;i<k;i++){
            ll num=(q-2*h2[i])/2;
            if(num-1<0) break;
            if(num-1>(ll)mx) continue;
            ans=mo(ans+res[i][num-1]);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

F

原文地址:https://www.cnblogs.com/YSFAC/p/11742935.html

时间: 2024-08-01 01:36:02

Educational Codeforces Round 75 (Rated for Div. 2)的相关文章

Educational Codeforces Round 75 (Rated for Div. 2) C. Minimize The Integer

链接: https://codeforces.com/contest/1251/problem/C 题意: You are given a huge integer a consisting of n digits (n is between 1 and 3?105, inclusive). It may contain leading zeros. You can swap two digits on adjacent (neighboring) positions if the swappi

Educational Codeforces Round 75 (Rated for Div. 2) A. Broken Keyboard

链接: https://codeforces.com/contest/1251/problem/A 题意: Recently Polycarp noticed that some of the buttons of his keyboard are malfunctioning. For simplicity, we assume that Polycarp's keyboard contains 26 buttons (one for each letter of the Latin alph

Educational Codeforces Round 75 (Rated for Div. 2) B. Binary Palindromes

链接: https://codeforces.com/contest/1251/problem/B 题意: A palindrome is a string t which reads the same backward as forward (formally, t[i]=t[|t|+1?i] for all i∈[1,|t|]). Here |t| denotes the length of a string t. For example, the strings 010, 1001 and

Educational Codeforces Round 75 (Rated for Div. 2) D. Salary Changing

链接: https://codeforces.com/contest/1251/problem/D 题意: You are the head of a large enterprise. n people work at you, and n is odd (i.?e. n is not divisible by 2). You have to distribute salaries to your employees. Initially, you have s dollars for it,

Educational Codeforces Round 75 (Rated for Div. 2)D(二分)

#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;pair<int,int>a[200007];int n;long long s;bool check(int x){ int num=0; long long sum=s; for(int i=n;i;--i){ if(a[i].first>=x) ++num; else if(a[i].second>=x&&s

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars There are n pillars aligned in a row and numbered from 1 to n. Initially each pillar contains exactly one disk. The i-th pillar contains a disk having radius ai. You can move these disks

Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations

原文链接:https://www.cnblogs.com/xwl3109377858/p/11405773.html Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations You are given a sequence of n pairs of integers: (a1,b1),(a2,b2),…,(an,bn). This sequence is called bad if it is

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

Educational Codeforces Round 36 (Rated for Div. 2) 题解

Educational Codeforces Round 36 (Rated for Div. 2) 题目的质量很不错(不看题解做不出来,笑 Codeforces 920C 题意 给定一个\(1\)到\(n\)组成的数组,只可以交换某些相邻的位置,问是否可以将数组调整为升序的 解题思路 首先如果每个数都能通过交换到它应该到的位置,那么就可以调整为升序的. 但实际上交换是对称的,如果应该在的位置在当前位置前方的数都交换完成,那么整体就是排好序的,因为不可能所有不在相应位置的数都在相应位置的后方.