K. Knitpicking

题意:给n种类型的字符串,每一种有三个属性,i,j,k,i是名字,j是方向,k是数量,方向是有left,right,和any,同一名字的left和right或left和any,right和any匹配,对这些类型的每一个进行排列,问最长的无匹配的是有多长

思路:根据题意模拟,我们记录每一个名字的L,R,A有多少,然后取d=L,R的最小,F=L,R的最大,如果d=0,那么就看a的大小,如果a=0,ans+=f,如果f=0,那么就要匹配一个,ff=1,其他情况则ans+=f,最后得到其他的全部的只有一个方向的,与一个两方向都有的,即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
struct node{
    int l=0,r=0,a=0;
};
map<string,node>mp;
set<string>s;
int32_t main() {
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        string s1,s2;
        int x;
        cin>>s1>>s2>>x;
        s.insert(s1);
        if(s2=="left"){
            mp[s1].l+=x;
        }
        else if(s2=="right"){
            mp[s1].r+=x;

        }
        else{
            mp[s1].a+=x;
        }
    }
    int ans=0;
    int ff=0;
    for(auto e:s){
        int l=mp[e].l;
        int r=mp[e].r;
        int a=mp[e].a;
        int d=min(l,r);
        int f=max(l,r);
        if(d==0){
            if(a==0){
                ans+=f;
            }
            else{
                if(f==0){
                    if(a>1){
                        ans+=1;
                        ff=1;
                    }
                    else{
                        ans+=1;
                    }
                }
                else{
                    ans+=f;
                    ff=1;
                }
            }
        }
        else{
            ans+=f;
            ff=1;
        }
    }
    if(ff==0){
        cout<<"impossible"<<endl;
    }
    else{
        cout<<ans+1<<endl;
    }
    return 0;
}
/*
 * a left 0
a right 0
a any 1
 */

A. Access Denied

题意:交互题,你需要猜测一个长度为1到20的字符串是什么,你每次给出一个字符串,然后都会给你反馈一个程序的运行时间,每个操作消耗多少时间,题目中给了,问你在2500次询问内怎么得到这个字符串

思路:我们最暴力的对每一位的字符都枚举,次数也不大,只有20 * 62,小于2500,我们首先是从长度进行枚举判断,如果程序运行时间一直为5ms,即字符串长度为20,那么我们就加字符串的长度,如果长度为14,即正确,然后其他情况,长度相等时,我们对每一位进行检查,首先每位字符如果相等,会消耗9ms,然后我们可以得到前e-1位是相同的,那么我们对第e位进行枚举,依次进行

diamond:

#include<bits/stdc++.h>
using namespace std;
//#define int long long
string ss="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int32_t main(){
    string s="0";
    cout<<s<<endl;
    string s1;
    while(getline(cin,s1)){
        if(s1.length()==20){
            s=s+'0';
            cout<<s<<endl;
        }
        else if(s1.length()==14){
            return 0;
        }
        else{
            int d=0;
            for(int i=15;i<s1.length();i++){
                if(s1[i]>='0'&&s1[i]<='9'){
                    d=d*10+(s1[i]-'0');
                }
                else {
//                    cout<<d<<endl;
                    break;
                }
            }

            //cout<<s1[15]<<" "<<s1[16]<<" "<<d<<endl;
            int e=(d-5)/9-1;
            int x=ss.find(s[e]);
            s[e]=ss[x+1];
            cout<<s<<endl;
        }
    }
}

J. Jet Set

题意:给n个在地球仪上的经纬度的位置,每次都是从当前走向下一个位置,走的路径是最短的弧线,最后一次是从n走到第1个位置,问走完之后是否都涵盖了所有的经度,经度从$-180<=x<180$。

思路:我们可以发现其实与纬度没啥关系,假如两者的距离是小于180度,那么是从小的走向大的即可,如果是大于180度,那么即是走外围,比如1到150,直接从1-150即可,如果是从1走到-175,正面走是从1到180,然后从-180到-175,总共184,如果我们反着走,先走到0,再走到-175,这样就是176,更短一些,当距离等于180度的时候,我们可以发现相对于球心对称,走的路径是半个最长的圆弧,我们可以直接走到赤道,再从赤道走向对立面即可,因为走到了赤道,所以经过了所有的经度线,当然我们还有一个要注意的,我们如果从1->170->-170->-50->0,虽然我们是走了360个度,但我们发现,从0到1没有被走过,因此有缝隙,这样是NO的,因此我们要* 2之后对两个数之间的数也要进行一个判断,注意正的没有180度,乘2后有359 度,无360度,只有负的才有

diamond:

#include<bits/stdc++.h>
using namespace std;
//#define int long long
int32_t main(){
    int n;
    cin>>n;
    int st=0;
    vector<int>q;
    for (int i = 0; i <n ; ++i) {
        int x,y;
        cin>>x>>y;
        q.push_back(y);
    }
    q.push_back(q[0]);
    vector<int>vis1(181);
    vector<int>vis2(182);
    vector<int>st1(366);
    vector<int>st2(366);
    for (int i = 0; i <n ; ++i) {
//        cout<<q[i]<<' '<<q[i+1]<<endl;
        if(abs(q[i]-q[i+1])==180){
            cout<<"Yes\n";
            return 0;
        }
        if(q[i]*q[i+1]>=0){
            int l= min(q[i],q[i+1]);
            int r= max(q[i],q[i+1]);
            for (int j = l*2; j <=r*2 ; ++j) {
                if(j>=0)st1[abs(j)]=1;
                else st2[abs(j)]=1;
            }
        }
        else{
            int r=max(q[i],q[i+1]);
            int l=min(q[i],q[i+1]);
            if(r-l<180){
                for (int j = 0; j <=r*2 ; ++j) {
                    st1[j]=1;
                }
                for (int j = l*2; j <=0 ; ++j) {
                    st2[-j]=1;
                }
            }
            else{
                for (int j = r*2; j <360 ; ++j) {
                    st1[j]=1;
                }
                for (int j = -360; j <=l*2 ; ++j) {
                    st2[-j]=1;
                }
            }
        }
    }
    for (int i = 1; i <360 ; ++i) {
        if(!st1[i]){
            double ans=(double)i/2;
            cout<<"no ";
            ::printf("%.1f",ans);
            return 0;
        }
    }
    for (int i = -360; i <0 ; ++i) {
        if(!st2[-i]){
            double ans=(double)i/2;
            cout<<"no ";
            ::printf("%.1f",ans);
            return 0;
        }
    }
    cout<<"yes\n";
}

H. Heating Up

题意:给定一个n片的披萨,每片有一个辣度,当你的耐受力>=a[i]的时候,你才能吃掉这块披萨,当你吃掉时,你的耐受力会提高这些数值,你能够吃的只能是相邻的两个,问你的耐受力初始最小是多少时,才能把这块披萨全部吃掉?

思路:很容易想到二分答案,但我们不晓得第一次该吃哪一块披萨,之间枚举的话是$n^2$的做法,因此这边用以给单调栈来处理,我们可以这样考虑,栈中放的是未被消灭的披萨,由于是环形,我们n* 2处理,这个披萨有两个属性,第一个是吃掉他需要多少耐受度,第二个是获得多少耐受度,假如当前mid=1,数组为 5 3 1 1 1 9,我们枚举到5 和3 的时候都>mid,则加入栈,枚举到1时,我们加入res,然后对栈进行消灭,我们发现无法消灭,那么继续往后走,枚举到第三个1时,发现可以消灭3了,那么就加上3,然后消灭5,枚举到9时,也可以消灭,最后st中无元素,就成功,假如在开头加个12,消灭5之后,我们的值也只有1+1+1+3+5=11,无法消灭12,那么枚举到9发现可以再消灭,假如是12 5 3 1 1 1 12 5 3 1 1 1 1 ,我们枚举到,第二个12时,无法消灭,但如果消灭了12,那么我们就可以消灭从第2个到第7个,因此我们将{12,12+5+3+1+1+1}加入到栈中,然后我们枚举到最后一个1的时候,发现就可以把前面全杀死,整体复杂度就是删了多少个,即为O(N)的,加个二分$n * log(1e13)$的,注意会爆long long,加个__INT128

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int  long long
int32_t main(){
    int n;
    cin>>n;
    vector<int>a(1e6+10);
    for (int i = 1; i <=n ; ++i) {
        cin>>a[i];
        a[n+i]=a[i];
    }
    n<<=1;
    auto check=[&](int mid){
        __int128 res=mid;
        stack<pair<int,int>>st;
        for (int i = 1; i <=n ; ++i) {
            if(a[i]<=res){
                res+=a[i];
                while (st.size()&&st.top().first<=res){
                    res+=st.top().second;
                    st.pop();
                }
            }
            else{
                st.push({a[i],res-mid+a[i]});
                res=mid;
            }
        }
        return st.empty();
    };

    int l=0,r=1e13+10;
    int ans;
    while (l<=r){
        int mid=l+r>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else{
            l=mid+1;
        }
    }
    cout<<ans<<endl;
}
posted on 2023-09-21 16:04  IR101  阅读(10)  评论(0编辑  收藏  举报  来源