zoukankan      html  css  js  c++  java
  • Codeforces #Round 785(Div.2)

    假的div2 C题没事写什么公式被卡精度了,掉分了gg

    ---------------------------------------------------

    A....几个每个字符串预先给好一个代表的值,给n个字符串,求和。

    题解:手速题。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<map>
    #define ll long long
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int  x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    map<string,int> mp;
    int n;
    ll ans=0;
    string st;
    
    int main()
    {
        n=read();mp["Tetrahedron"]=4;
        mp["Cube"]=6;
        mp["Octahedron"]=8;
        mp["Dodecahedron"]=12;
        mp["Icosahedron"]=20;
        for(int i=1;i<=n;i++)
            cin>>st,ans+=mp[st];
        cout<<ans;
        return 0;
    }

    B.有两种课,每种课都有很多节,每节课有一段时间l..r,你要从两种课中都选一节,使得中间的休息时间最长。

    题解:两边都分别记一下最小值,最大值。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<map>
    #define ll long long
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int  x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int mx1,mx2,mn1=INF,mn2=INF;
    int n,m,ans=0;
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            int l=read();int r=read();
            mx1=max(mx1,l);mn1=min(mn1,r);
        }
        m=read();
        for(int i=1;i<=m;i++)
        {
            int l=read();int r=read();
            mx2=max(mx2,l);mn2=min(mn2,r);
        }
        ans=max(ans,max(mx1-mn2,mx2-mn1));
        cout<<ans;
        return 0;
    }

    C.有一个大小为n的粮仓,一开始是满的,每天都会运来m的粮食,但是不能超过大小上限,然后运来后会有不速之客来吃,第i天吃掉i的粮食,求第几天粮食被吃完了。

    n,m<=10^18

    正确解法:二分答案,等差数列求和

    我的错误解法:解一元二次方程,结果用了double被卡精度,FST了,改成long double 就过了.... 心累。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<map>
    #include<cmath>
    #define ll unsigned long long
    #define double long double
    #define INF 2000000000
    #define eps 1e-8
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    ll n,m,size;
    
    int main()
    {
        n=read();m=read();
        if(n<=m)cout<<n;
        else
        {
            double mm=sqrt((double)n*2.0-(double)m*2.00+0.25)-0.5;
            m+=(ll)ceil(mm);
            cout<<m;
        }
        return 0;
    }

    D.给定一个长度为n的括号序列,求特殊的括号子序列的数量。特殊的是指,前一半是(,后一半是)     n<=200000

    左边有n个左括号,右边有m个右括号,我们为了去重要求一定选最右的哪个左括号,这是侯答案数量是∑C(n,k-1)*C(m,k) k=1..min(n,m)

    然后我们会发现这个式子就等于C(n+m-1,m-1),所以预处理好阶乘和逆元,就可以算啦。

    复杂度O(n)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<map>
    #include<cmath>
    #define ll long long
    #define INF 2000000000
    #define mod 1000000007
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n;
    char s[200005];
    ll p[200005],l[200005];
    int num1=0,num2=0;
    ll ans=0;
    
    ll work(int n,int c)
    {
        return p[n]*l[c]%mod*l[n-c]%mod;
    }
    
    int main()
    {
        scanf("%s",s+1);n=strlen(s+1);
        p[0]=l[0]=l[1]=1;
        for(int i=1;i<=200000;i++)p[i]=p[i-1]*i%mod;
        for(int i=2;i<=200000;i++)l[i]=(mod-mod/i)*l[mod%i]%mod;
        for(int i=2;i<=200000;i++)l[i]=l[i]*l[i-1]%mod;
        for(int i=1;i<=n;i++)num2+=(s[i]==')');
        for(int i=1;i<=n;i++)
        {
            if(s[i]==')')num2--;
            else
            {num1++;ans=(ans+work(num1+num2-1,num2-1))%mod;}
        }
        cout<<ans;
        return 0;
    }

    E.给定一个1-n的全排列,一开始是1到n摆放。q个操作,每次交换一对数,然后要求交换后的逆序对数量。n<=200000,q<=50000 题目有4s

    1.分块+树状数组。复杂度应该是n^1.5*logn

    2.树状数组套平衡树.....(ditoly真的强,几下就切完了)复杂度nlog^2n

    分块 2308ms

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define MAXN 200005
    #define MAXB 455
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n,m,size;
    ll ans=0;
    int c[MAXB][MAXN],s[MAXN],block[MAXN];
    
    void renew(int num,int x,int ad)
    {
        for(;x<=n;x+=x&(-x))
            c[num][x]+=ad;
    }
    
    int query(int num,int x)
    {
        int sum=0;
        for(;x;x-=x&(-x))
            sum+=c[num][x];
        return sum;
    }
    
    ll solve(int l,int r,int num)
    {
        if(l>r)return 0;
        int sum=0;
        if(block[l]==block[r])
        {
            for(register int i=l;i<=r;i++)sum+=(s[i]<num);
            return(ll)sum;
        }
        for(register int i=block[l]+1;i<block[r];i++)
            sum+=query(i,num);
        if(block[l-1]!=block[l])sum+=query(block[l],num);
        else for(register int i=l;block[i]==block[l]&&i<=r;i++)sum+=(s[i]<num);
        if(block[l]==block[r]) return (ll)sum;
        if(block[r+1]!=block[r])sum+=query(block[r],num);
        else for(register int i=r;block[i]==block[r]&&i>=l;i--)sum+=(s[i]<num);
        return(ll)sum;
    }
    
    int main()
    {
        n=read();m=read();size=sqrt(n);
        for(int i=1;i<=n;i++)block[i]=(i-1)/size+1;
        for(int i=1;i<=n;i++)s[i]=i,renew(block[i],i,1);
        for(register int i=1;i<=m;i++)
        {
            int u=read(),v=read();if(u>v)swap(u,v);
            if(u==v){printf("%lld
    ",ans);continue;}
            if(u!=v-1)
            {
                ans+=2*solve(u+1,v-1,s[v]);
                ans-=2*solve(u+1,v-1,s[u]);
            }
            renew(block[u],s[u],-1);renew(block[u],s[v],1);
            renew(block[v],s[v],-1);renew(block[v],s[u],1);
            swap(s[u],s[v]);
           // cout<<ans;
            if(s[u]>s[v])ans++;else ans--;
            printf("%lld
    ",ans);
        }
        return 0;
    }

    做法2以后补

  • 相关阅读:
    hdu 5387 Clock (模拟)
    CodeForces 300B Coach (并查集)
    hdu 3342 Legal or Not(拓扑排序)
    hdu 3853 LOOPS(概率DP)
    hdu 3076 ssworld VS DDD(概率dp)
    csu 1120 病毒(LICS 最长公共上升子序列)
    csu 1110 RMQ with Shifts (线段树单点更新)
    poj 1458 Common Subsequence(最大公共子序列)
    poj 2456 Aggressive cows (二分)
    HDU 1869 六度分离(floyd)
  • 原文地址:https://www.cnblogs.com/FallDream/p/codeforces785.html
Copyright © 2011-2022 走看看