• Codeforcs 每日一练 678C+527C+1012C


    678C Joty and Chocolate

    传送门
    镜像
    1600 数论
    题意:n块瓷砖从1~n编号,Joty可以将其中编号为a的倍数的瓷砖涂成红色,编号为b的倍数的瓷砖涂成蓝色,每涂一块红色的瓷砖可以得到p块巧克力,而蓝色的瓷砖则提供q块巧克力,最大化Joty能够得到的巧克力数。
    水题~,假设x块编号是a的倍数,y块编号是b的倍数,z块编号是a和b最小公倍数的倍数,当p>q的情况下,则x+z块涂成红色,y-z块涂成蓝色,其他情况同理。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define IOS  ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    ll n,a,b,p,q;
    ll gcd(ll x,ll y){if(y==0)return x;return gcd(y,x%y);}
    int main()
    {
        IOS
        cin>>n>>a>>b>>p>>q;
        ll m=a*b/gcd(a,b);
        m=n/m;
        a=n/a-m;
        b=n/b-m;
        ll ans;
        if(p>=q)ans=(a+m)*p+b*q;
        else ans=(b+m)*q+a*p;
        cout<<ans;
        return 0;
    }
    

    527C Glass Carving

    传送门
    镜像
    1800 数据结构
    题意:一个长h宽w的玻璃砖,每次垂直一条边切割,问每次切割后的最大面积
    开两个set和两个multiset就可以解出来了,两个set分别记录x轴和y轴上面的切割点(初始就分别扔进去0,w和0,h),multiset则记录x轴或y轴上切割产生的线段,对于每次切割后,找出当前切割点两端最近的点,然后在multiset里把这段的长度erase掉,把新生成的两段插进去,最后输出两个multiset里最大值的乘积即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define IOS  ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    ll n,w,h;
    set<ll> x,y;
    multiset<ll> a,b;
    int main()
    {
        IOS
        cin>>w>>h>>n;
        y.insert(h);y.insert(0);
        x.insert(w);x.insert(0);
        a.insert(h);
        b.insert(w);
        while(n--){
            char s;
            ll l;
            cin>>s>>l;
            if(s=='H'){
                auto i=y.lower_bound(l);
                if(*i>l)i--;
                auto j=y.upper_bound(l);
                ll tmp=*i-*j;
                auto m=a.lower_bound(*j-*i);
                a.erase(m);
                a.insert(l-*i);
                a.insert(*j-l);
                y.insert(l);
            }else{
                auto i=x.lower_bound(l);
                if(*i>l)i--;
                auto j=x.upper_bound(l);
                ll tmp=*i-*j;
                auto m=b.lower_bound(*j-*i);
                b.erase(m);
                b.insert(l-*i);
                b.insert(*j-l);
                x.insert(l);
            }
            auto p=a.end(),q=b.end();
            q--;
            p--;
            cout<<(*p)*(*q)<<endl;
        }
        return 0;
    }
    

    小姐姐的平衡树做法:

    #include<iostream>
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/tree_policy.hpp>
    #include<ext/pb_ds/hash_policy.hpp> 
    using namespace std;
    using namespace __gnu_pbds;
    typedef long long ll;
    tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> x,y;
    tree<pair<int,int>,null_type,greater<pair<int,int>>,rb_tree_tag,tree_order_statistics_node_update> xx,yy;
    cc_hash_table<int,int> hx,hy;
    int w,h,n;
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin>>w>>h>>n;
    	x.insert(0);
    	x.insert(w);
    	y.insert(0);
    	y.insert(h);
    	xx.insert(make_pair(w,++hx[w]));
    	yy.insert(make_pair(h,++hy[h]));
    	for(int i=0;i<n;i++)
    	{
    		char c;
    		int num;
    		cin>>c>>num;
    		if(c=='V')
    		{
    			int rank=x.order_of_key(num);
    			int pre=*x.find_by_order(rank-1);
    			int nxt=*x.find_by_order(rank);
    			xx.erase(make_pair(nxt-pre,hx[nxt-pre]--));
    			xx.insert(make_pair(num-pre,++hx[num-pre]));
    			xx.insert(make_pair(nxt-num,++hx[nxt-num]));
    			x.insert(num);
    		}
    		else if(c=='H')
    		{
    			int rank=y.order_of_key(num);
    			int pre=*y.find_by_order(rank-1);
    			int nxt=*y.find_by_order(rank);
    			yy.erase(make_pair(nxt-pre,hy[nxt-pre]--));
    			yy.insert(make_pair(num-pre,++hy[num-pre]));
    			yy.insert(make_pair(nxt-num,++hy[nxt-num]));
    			y.insert(num);
    		}
    		cout<<(ll)xx.find_by_order(0)->first*(ll)yy.find_by_order(0)->first<<endl;
    	} 
    	return 0;
    }
    

    1012C Hills

    传送门
    镜像
    2000 dp
    题意:一共n座山,每花费1h可以使一座山降低1的高度,最少花费多少时间可以使存在k座山的高度严格大于两侧的山的高度。输出k从1~n2lceil frac{n}{2} ceil的结果。
    一开始想的做法是dp[i][j][0]代表前i个有j个满足,并且最后一个不取,dp[i][j][1]代表前i个有j个满足,并且最后一个取,但是状态转移尬住了,因为还要考虑倒数第二个的状态,那开三维就好了,dp[i][j][0]代表前i个有j个满足,并且最后两个都不取,dp[i][j][2]代表前i个有j个满足,并且取最后一个,dp[i][j][1]代表前i个有j个满足,并且取倒数第二个。
    那么状态转移方程就很好推了:

    dp[i][j][1]=dp[i-1][j][2]+max(0,a[i]-a[i-1]+1)
    dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1])
    dp[i][j][2]=min(dp[i-1][j-1][0]+max(0,a[i-1]-a[i]+1),dp[i-1][j-1][1]+max(0,min(a[i-1],a[i-2]-1)-a[i]+1))
    

    然后就是初始化,不确定的和非法状态存为极大值,显然dp[1][1][2]=0,并且dp[i][0][0]=0(1<=i<=n)从2开始转移就可以A了

    #include<bits/stdc++.h>
    using namespace std;
    #define IOS  ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define maxn 5005
    int n,a[maxn],dp[maxn][maxn][3];
    int main()
    {
        IOS
        cin>>n;
        for (int i = 1; i <=n ; ++i) {
            cin>>a[i];
            for (int j = 0; j <=n ; ++j) {
                for (int k = 0; k <=2 ; ++k) {
                    dp[i][j][k]=2146870000;
                }
            }
            dp[i][0][0]=0;
        }
        dp[1][1][2]=0;
        for (int i = 2; i <=n ; ++i) {
            for (int j = 1; j <=(i+1)/2 ; ++j) {
                dp[i][j][2]=min(dp[i-1][j-1][0]+max(0,a[i-1]-a[i]+1),dp[i-1][j-1][1]+max(0,min(a[i-1],a[i-2]-1)-a[i]+1));
                dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]);
                dp[i][j][1]=dp[i-1][j][2]+max(0,a[i]-a[i-1]+1);
            }
        }
        for (int k = 1; k <=(n+1)/2 ; ++k) {
            cout<<min(dp[n][k][2],min(dp[n][k][0],dp[n][k][1]))<<" ";
        }
        return 0;
    }
    
  • 相关阅读:
    软件测试描述错误
    软件测试homework2
    第九次
    第七次作业
    第六次作业
    第五次作业
    第四次作业
    第三次
    软件测试Lab2 Selenium及自动化测试
    软件测试(四)主路径覆盖hw3
  • 原文地址:https://www.cnblogs.com/Bazoka13/p/12623390.html
Copyright © 2020-2023  润新知