ABC 223 A~F (C尺取,D拓扑排序,E思维,F分块)

22 篇文章 0 订阅
12 篇文章 0 订阅

链接

A Exact Price

对n取余看是否为0,注意特判0.

B String Shifting

找最小,最大,我们发现他是有个环形的字符串那么我们可以把n个字符串提取出来,排序即可。

C - Doukasen

我们从两端往中间走,看那一端先到交界处这段就要向前走下一块,速度会变,到了交界处另一端减去当前时间走的即可(速度不变),所以我们只需要比较走过两端最后一块的时间为多长,取小的即可。长度用double用ll是不对的哦

ll n,m;
 
struct node
{
    double a, b;
}q[MAX];
bool cmp(node a,node b){
    return a.a<b.a;
}
void solve()
{
    cin>>n;    
    for(int i=1;i<=n;i++){
        cin>>q[i].a>>q[i].b;                
    }
    ///sort(q+1,q+1+n,cmp);
    
    ll l=1,r=n;
    double sum=0.0;
    while(l<=r){        
        if(l!=r){
            double t1,t2;
            t1=q[l].a*1.0/q[l].b;
            t2=q[r].a*1.0/q[r].b;
            //cout<<t1<< " "<< t2<<endl;
            if(t1>t2){
                sum+=t2*q[l].b;
                q[l].a-=t2*q[l].b;
                r--;
            }else if(t2>t1){
                sum+=q[l].a;
                q[r].a-=t1*q[r].b;
                l++;
            }else if(t1==t2){
                sum+=q[l].a;
                l++;
                r--;
            }
        }else {
            sum+=q[l].a*1.0/2;            
            l++;r--;
            break;
        }  
    }
    printf("%.20lf\n",sum);
}

D - Restricted Permutation

题意:

给出n个点,m个条件:

  • 每个条件两个参数,a,b,意味着a在b,之前出现。
    看完这个条件是不是想到了,前置条件,这不就是拓扑排序的意思吗?直接写;
ll n,m;
std::vector<ll> v[MAX];
ll in[MAX],out[MAX];
ll b[MAX],a[MAX];
priority_queue<ll,vector<ll>,greater<ll> >mx;
void topsort(){
    
    for(ll i=1;i<=n;i++){
        if(in[i]==0){
            mx.push(i);
            b[i]==1;
        }
    }
    ll cnt=0;
    while(!mx.empty()){
        ll top = mx.top();
        a[++cnt]=top;
        mx.pop();
        for(int i=0 ;i<v[top].size();i++){
            ll j=v[top][i];
            in[j]--;
            if(b[j]==0&&in[j]==0){
                b[j]=1;
                mx.push(j);
            }
        }
    }
    if(cnt==n) {
        for(int i=1;i<=n;i++) cout<< a[i]<<" ";
    }else puts("-1");
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        ll x,y;
        cin>>x>>y;
        in[y]++;
        out[x]++;
        v[x].push_back(y);
    }
    topsort();
}

E - Placing Rectangles

题意:

很简单:就是给出你一个 n × m n\times m n×m的矩形,让你让三个面积为a,b,c的矩形,看看是否能够放进去。

分析:

如果我们放三个矩形在一个矩形中有多少种那?
我们画一下就知道了:
第一种三个横着的:
第二种三个竖着的:
第三种一个竖着两个横着:
第四种一个横着两个竖着:
好没了,就这四种,那么我们可以直接判断了,任意一种能放下就说明能放下,都放不下那就是放不下呗。

bool check1(ll a, ll b, ll c){
    ll a1=(a+x-1)/x;
    ll ty=y-a1;
    ll b1=(b+ty-1)/ty;
    ll c1=(c+ty-1)/ty;
    if(b1+c1<=x) return 1;
    
    a1=(a+y-1)/y;
    ty=x-a1;
    b1=(b+ty-1)/ty;
    c1=(c+ty-1)/ty;
    if(b1+c1<=y) return 1;
 
    return 0;
}
 
ll a,b,c;
 
void solve()
{
    cin>>x>>y>>a>>b>>c;
    if(a+b+c>x*y) puts("No");
    else{
        ///1
        ll a1=(a+x-1)/x;
        ll b1=(b+x-1)/x;
        ll c1=(c+x-1)/x;        
        if(a1+b1+c1<=y){
            puts("Yes");
            return ;
        }
        ///2
        a1 = (a+y-1)/y;
        b1 = (b+y-1)/y;
        c1 = (c+y-1)/y;
        if(a1+b1+c1<=x){
            puts("Yes");
            return ;
        }
        ///3
        if(check1(a,b,c)||check1(b,a,c)|| check1(c,b,a)){
            puts("Yes");
            return ;
        }
        puts("No");
    }
}

F - Parenthesis Checking

题意:

给出长度为n的括号序列,对其进行q次操作:

  • 1 l,r将l,r位置上的符号进行互换。
  • 2 l,r询问l~r,是否是规范的序列。

分析:

我们可以采用分块来做,交换的话我们改变的是两个点,影响的是这两个点所在的 n \sqrt n n 序列,询问,我们只需要看看两端即可。复杂度是 O ( n n ) O(n\sqrt n) O(nn )


string str;
ll n,m;
ll a[MAX],b[MAX];
void solve()
{
    cin>>n>>m;
    ll num = 0 ;
    while(num*num <n) num++;
    cin>>str;
    for(int i=0;i*num<n;i++){
        a[i] = 0;
        b[i] = 0;
        for(int j=0;j<num;j++){
            if(str[i*num+j]=='(') a[i]++;
            else {
                a[i]--;
            }
            if(b[i] > a[i]){
                b[i] = a[i];
            }
        }
    }
    ll l, r, op; 
    while(m--){
        cin>>op>>l>>r;
        l--;r--;
        if(op==1){
            swap(str[l],str[r]);
            ll x = l / num;
            a[x] = 0;
            b[x] = 0;
            for(int j=0;j<num;j++){
                if(str[x*num+j]=='('){
                    a[x]++;
                }else {
                    a[x]--;
                }
                if(b[x]>a[x]) b[x]=a[x];
            }
            x = r / num;
            a[x] = 0;
            b[x] = 0;
            for(int j=0;j<num;j++){
                if(str[x*num+j]=='('){
                    a[x]++;
                }else {
                    a[x]--;
                }
                if(b[x]>a[x]) b[x]=a[x];
            }            
        }else {
            ll flag=0,sum=0;
            if(l/num <r/num){
                ll i = l/num;
                for(int j=l%num;j<num;j++){
                    if(str[i*num+j]=='(') sum++;
                    else sum--;
                    if(sum<0) flag++;
                }

                for(int i=l/num+1;i<r/num;i++){
                    if(sum+b[i]<0) flag++;
                    sum+=a[i];
                }
                i=r/num;
                for(int j=0;j<=r%num;j++){
                    if(str[i*num+j]=='(') sum++;
                    else sum--;
                    if(sum<0) flag++;
                }
                if(sum!=0) flag++;
            }else {
                ll i=l/num;
                for(int j=l%num;j<=r%num;j++ ){
                    if(str[i*num+j]=='(') sum++;
                    else sum--;
                    if(sum<0) flag++;
                }
                if(sum!=0) flag++;
            }
            if(flag>0) puts("No");
            else puts("Yes");
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值