• 2019icpc陕西省赛


    前言:学长下了硬指标要我们把题补到金牌线,那就补吧。总的来说拿金牌可能并不难,就我目前能力所及(4个签到+1个思维+1个图论)可能除了图论题我现场调不完(事实上我调了整整一天qwq,不过没有用题解给的前缀和,用了自己擅长的Segment_Tree来写。)另外5个题我现场能写出来吧,大概就是在去年以我现在的水准solo能拿个银?(你在想peach)。这套题的质量我觉得很好,开场几个签到也很有意思。I题用了dfs序+线段树最后ac了。

    E:Turn it off

    其实就是很单纯的二分吧,不过我写的时候Re了,注意跳到最后如果跳出了记得break

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    string s;int n,k;
    bool check(int x){
        int cur;
        for(int i=1;i<=n;i++){
            if(s[i]=='1'){
                cur=i;break;
            }
        }
        int cnt=0;
        while(cur<=n){
            cur+=x;cnt+=1;
            if(cur>n) break;
            while(s[cur]=='0') ++cur;
        }
        if(cnt<=k) return true;
        return false;
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&k);
            cin>>s;s=" "+s;    
            int l=1,r=n/k+1;
            while(l<r){
                int mid=(l+r)>>1;
                if(check(mid)) r=mid;
                else l=mid+1;
            }
            printf("%d
    ",l);
        }
    }
    /*
    1
    12 4
    000100000000
    */
    View Code

    F:K-hour-clock

    就是纯思维题,想清楚两者的关系,如果x+y==z直接ok的,否则看x+y-z与x和z的大小关系。

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            ll cur=x+y-z;
            if(x+y==z){
                cout<<max(x,z)+1<<endl;continue;
            }
            if(cur<=x||cur<=z){puts("-1");continue;}
            cout<<cur<<endl;
        }
    }
    /*
    1
    0 5 6
    */
    View Code

    L:Digit Product

     这个也是思维规律题,可以发现连续的10个数必定为0,然后你先特判一下L,R的间距呗,如果小于10直接暴力上

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    ll f(ll x){
        ll ans=1;
        while(x){
            ans*=(x%10);
            x/=10;
        }
        return ans;
    }
    int main(){
        int T;cin>>T;
        ll ans=0;
        while(T--){
            int l,r;cin>>l>>r;
            if(r-l+1>=10){
                cout<<"0"<<endl;
                continue;
            }
            ll ans=1;
            rep(i,l,r){
                ans=(ans*f(i))%mod;
            }
            cout<<ans<<endl;
        }
    }
    View Code

    B:Grid with Arrows

    图论欧拉回路+并查集判断。找indeg,符合欧拉回路的情况先用dsu判断是否都在1棵树上,倘若不会直接No,如果是的话再看每个点的入度,只准有0个或1个点的入度为0这个时候输出Yes,其他输出No

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    int fa[maxn];
    int find(int x){
        while(x!=fa[x]){
            x=fa[x]=fa[fa[x]];
        }
        return x;
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            int n,m;scanf("%d%d",&n,&m);
            int indeg[n+5][m+5];mem(indeg,0);
            char a[n+5][m+5];mem(a,0);
            rep(i,1,n){
                rep(j,1,m){
                    cin>>a[i][j];
                    fa[(i-1)*m+j]=(i-1)*m+j;
                }
            }
            rep(i,1,n){
                rep(j,1,m){
                    int qwq;cin>>qwq;
                    if(a[i][j]=='u'){
                        if(i-qwq>0){
                            indeg[i-qwq][j]+=1;
                            int eu=find((i-1)*m+j);
                            int ev=find((i-qwq-1)*m+j);
                            if(eu!=ev) fa[ev]=eu;
                        }                        
                    }
                    if(a[i][j]=='d'){
                        if(i+qwq<=n){
                            indeg[i+qwq][j]+=1;
                            int eu=find((i-1)*m+j);
                            int ev=find((i+qwq-1)*m+j);
                            if(eu!=ev) fa[ev]=eu;                        
                        }
                    }
                    if(a[i][j]=='r'){
                        if(j+qwq<=m){
                            indeg[i][j+qwq]+=1;
                            int eu=find((i-1)*m+j);
                            int ev=find((i-1)*m+j+qwq);
                            if(eu!=ev) fa[ev]=eu;                        
                        }
                    }
                    if(a[i][j]=='l'){
                        if(j-qwq>0){
                            indeg[i][j-qwq]+=1;                    
                            int eu=find((i-1)*m+j);
                            int ev=find((i-1)*m+j-qwq);
                            if(eu!=ev) fa[ev]=eu;    
                            
                        }
                    }
                }
            }
            int cnt=0;
            rep(i,1,n){
                rep(j,1,m){
                    if(indeg[i][j]==0){
                        ++cnt;
                    }
                    if(cnt==2){
                        break;
                    }
                }
            }
            int cur=find(2),lol=1;
            rep(i,2,n*m){
                if(find(i)!=find(i-1)){
                    lol=0;
                }
            }
            if((cnt==1||cnt==0)&&lol==1) puts("Yes");
            else puts("No");
        }
    }
    /*
    1
    2 3
    rdd
    url
    2 1 1
    1 1 2
    */
    View Code

    C:0689

    思维题,我队友说这个可能只有CF1700的难度。我后来想想也是如此。做法大概就是利用前缀和。如果当前是0,则找后面0的数量;如果当前是8,则找后面8的数量;如果当前是6,则找后面9的数量;如果是9,则找后面6的数量。总而言之大概意思就是0和0互换还是当前不变的,8和8不变,9和6不变,6和9不变。然后总共次数是(n+1)*n/2。然后记得这个题有个坑。必须执行一次操作,如果是66的话,其实只有3个变形,因为66是没有执行操作的

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e6+5;
    int a[maxn],b[maxn],c[maxn],d[maxn];
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            string s;cin>>s;
            int len=s.length();
            s=" "+s;
            for(int i=0;i<=len;i++){
                a[i]=b[i]=c[i]=d[i]=0;
            }
            rep(i,1,len){
                if(s[i]=='0') a[i]=a[i-1]+1;
                else a[i]=a[i-1];
                if(s[i]=='6') b[i]=b[i-1]+1;
                else b[i]=b[i-1];
                if(s[i]=='8') c[i]=c[i-1]+1;
                else c[i]=c[i-1];
                if(s[i]=='9') d[i]=d[i-1]+1;
                else d[i]=d[i-1];
            }
            ll ans=1ll*(len+1)*len/2+1;
            ans-=(a[len]+c[len]);
            rep(i,1,len){
                if(s[i]=='0') ans-=a[len]-a[i];
                if(s[i]=='6') ans-=d[len]-d[i];
                if(s[i]=='8') ans-=c[len]-c[i];
                if(s[i]=='9') ans-=b[len]-b[i];
            }
            if(b[len]==len||d[len]==len) ans--;
            cout<<ans<<endl;
        }
    }
    View Code

    I:Unrooted Trie

    树上dfs序+线段树。

    首先检查每个节点的边集,如果在边集中出现aaa或aabb这样的重复情况,必然是不行的,直接输出0。然后搞dfs序。

    然后遍历每个节点,首先确定这个节点边集中两条重复的边对应的点t1,t2。然后分类讨论。

    如果这个节点在DFS序里在t1,t2的前面,则是t1,t2的根,那么合法的根节点就是t1,t2的子树,就确定了这个节点的合法根节点区间。

    如果这个节点在DFS序里在t1,t2的中间,则合法的根节点是t1的子树的补集加上t2的子树,保存这个节点的合法根节点区间。

    最后用线段树统计点大小为0的数量即可。

    注意细节吧。

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    class segment_tree{
        public:
            struct node{
                int l,r;
                int sum,lz;
            }tree[maxn<<2];
            
            inline void build(int i,int l,int r){
                tree[i].l=l;tree[i].r=r;tree[i].lz=0;
                if(l==r){
                    tree[i].sum=0;
                    return ;
                }
                int mid=(l+r)>>1;
                build(i*2,l,mid);
                build(i*2+1,mid+1,r);
                tree[i].sum=tree[2*i].sum+tree[2*i+1].sum;
            }
            
            inline void push_down(int i){
                if(tree[i].lz!=0){
                    tree[2*i].lz=tree[i].lz;
                    tree[2*i+1].lz=tree[i].lz;
                    int mid=(tree[i].l+tree[i].r)/2;
                    tree[2*i].sum=tree[i].lz*(mid-tree[2*i].l+1);
                    tree[2*i+1].sum=tree[i].lz*(tree[2*i+1].r-mid);
                    tree[i].lz=0;
                }
                return ;
            }
            
            inline void add(int i,int l,int r,int k){
                if(tree[i].r<=r&&tree[i].l>=l){
                    tree[i].sum=k*(tree[i].r-tree[i].l+1);
                    tree[i].lz=k;
                    return ;
                }
                push_down(i);
                if(tree[i*2].r>=l) add(i*2,l,r,k);
                if(tree[i*2+1].l<=r) add(i*2+1,l,r,k);
                tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
            }
            
            inline int search(int i,int l,int r){
                if(tree[i].l>=l&&tree[i].r<=r)
                    return tree[i].sum;
                if(tree[i].r<l||tree[i].l>r) return 0;
                push_down(i);
                int s=0;
                if(tree[i*2].r>=l) s+=search(i*2,l,r);    
                if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r);    
                return s;
            }
    }st;
    int tot,head[maxn];
    struct E{
        int to,next;
        char w;
    }edge[maxn<<1];
    void add(int u,int v,char w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,tim,dfn[maxn],siz[maxn];
    void dfs1(int x,int f){
        siz[x]=1;
        dfn[x]=++tim;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==f) continue;
            dfs1(v,x);
            siz[x]+=siz[v];
        }
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            fill(head,head+2*n+5,-1);
            fill(dfn,dfn+n+5,0);
            fill(siz,siz+n+5,0);
            tot=0,tim=0;
            for(int i=1;i<n;i++){
                int u,v;char w;scanf("%d %d %c",&u,&v,&w);
                add(u,v,w);add(v,u,w);
            }
            int fg=0;
            for(int x=1;x<=n;x++){
                int vn[30];mem(vn,0);
                for(int i=head[x];i!=-1;i=edge[i].next){
                    char w=edge[i].w;
                    vn[w-'a']+=1;
                }
                int qwqwq=0;
                rep(i,0,25){
                    if(vn[i]>=2) qwqwq++;
                    if(vn[i]>=3){
                        fg=1;break;
                    }
                }
                if(fg) break;
                if(qwqwq>=2){
                    fg=1;break;
                }
            }
            if(fg){puts("0");continue;}
            dfs1(1,0);
            st.build(1,1,n);
            for(int u=1;u<=n;u++){
                map<char,int> mp;
                for(int j=head[u];j!=-1;j=edge[j].next){
                    int v=edge[j].to;char w=edge[j].w;
                    if(!mp[w]) mp[w]=v;
                    else{
                        int f1=mp[w],f2=v;
                        if(dfn[f1]>dfn[u]&&dfn[f2]>dfn[u]){
                            int L,R;
                            if(dfn[f1]<dfn[f2]){L=f1,R=f2;}
                            else{L=f2,R=f1;}
                            st.add(1,1,dfn[L]-1,1);
                            if(dfn[L]+siz[L]>n) goto end;
                            st.add(1,dfn[L]+siz[L],dfn[R]-1,1);
                            end:;
                            if(dfn[R]+siz[R]>n) break;
                            st.add(1,dfn[R]+siz[R],n,1);
                        }
                        else if(dfn[f1]>dfn[u]&&dfn[u]>dfn[f2]){
                            st.add(1,dfn[u],dfn[f1]-1,1);
                            if(dfn[f1]+siz[f1]>n) break;
                            st.add(1,dfn[f1]+siz[f1],dfn[u]+siz[u]-1,1);                        
                        }
                        else if(dfn[f2]>dfn[u]&&dfn[u]>dfn[f1]){
                            st.add(1,dfn[u],dfn[f2]-1,1);
                            if(dfn[f2]+siz[f2]>n) break;
                            st.add(1,dfn[f2]+siz[f2],dfn[u]+siz[u]-1,1);
                        }
                        break;    
                    }
                }
            }
            printf("%d
    ",n-st.search(1,1,n));
        }
    }
    View Code
  • 相关阅读:
    数字音乐均衡器
    移植x264到vs2008之二
    无线连接频繁掉线,解决方法之telnet命令突破ddwrt端口最大数连接限制分析
    最新开发的消费平台开发过程 持续更新(二)
    .net 4.0 下请求验证模式变化 应对方法
    DDWRT无线参数解读
    利用 Application_Error 捕获所有异常
    location.reload() 和 location.replace()的区别和应用
    纯CSS 实现组织架构图,学习
    Syslog架设windows日志服务器
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13714747.html
Copyright © 2020-2023  润新知