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

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

    A. Xenia and Divisors

    ---

    将n个数3个一组分成满足条件的n/3组。

    由于数字最多是7,所以只有124、126、136三种分组方式。

    先分出所有的136,再分出124,126。若所有数字都用光则分组成功。

    ---

    #include <iostream>
    
    using namespace std;
    int n;
    int a[10]={0};
    bool check(){
        for (int i=1;i<=7;i++) if (a[i]<0) return true;
        return false;
    }
    
    int main()
    {
        cin>>n;
        for (int i=0;i<n;i++){
            int t;
            cin>>t;
            a[t]++;
        }
        if (n%3!=0){
            cout<<-1<<endl;
            return 0;
        }
        if (a[5]>0||a[7]>0){
            cout<<-1<<endl;
            return 0;
        }
        int c1,c2,c3;
        c1=a[3];
        a[1]-=c1;
        a[3]-=c1;
        a[6]-=c1;
        if (check()){
            cout<<-1<<endl;
            return 0;
        }
        c2=a[6];
        a[1]-=c2;
        a[2]-=c2;
        a[6]-=c2;
        if (check()){
            cout<<-1<<endl;
            return 0;
        }
        c3=a[4];
        a[1]-=c3;
        a[2]-=c3;
        a[4]-=c3;
        if (check()){
            cout<<-1<<endl;
            return 0;
        }
        if (c1*3+c2*3+c3*3!=n){
            cout<<-1<<endl;
            return 0;
        }
        for (int i=1;i<=7;i++) if (a[i]!=0) {
            cout<<-1<<endl;
            return 0;
        }
        for (int i=0;i<c3;i++) cout<<"1 2 4"<<endl;
        for (int i=0;i<c2;i++) cout<<"1 2 6"<<endl;
        for (int i=0;i<c1;i++) cout<<"1 3 6"<<endl;
        return 0;
    }
    -----------------------------

    B. Xenia and Spies

    ---

    n个人,s要将纸条传到f。传一次用时1。

    有m次观察,对于每次观察,第t秒时区间[l,r]不能传递或接受纸条。

    问最少用多少时间才能将纸条传到f。

    贪心传递即可,若能传递则尽可能传递。

    若m次观察后还没有传到f,则要继续传到f。

    ---

    /** head-file **/
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <list>
    #include <set>
    #include <map>
    #include <algorithm>
    
    /** define-for **/
    
    #define REP(i, n) for (int i=0;i<int(n);++i)
    #define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
    #define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
    #define REP_1(i, n) for (int i=1;i<=int(n);++i)
    #define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
    #define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
    #define REP_N(i, n) for (i=0;i<int(n);++i)
    #define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
    #define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
    #define REP_1_N(i, n) for (i=1;i<=int(n);++i)
    #define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
    #define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)
    
    /** define-useful **/
    
    #define clr(x,a) memset(x,a,sizeof(x))
    #define sz(x) int(x.size())
    #define see(x) cerr<<#x<<" "<<x<<endl
    #define se(x) cerr<<" "<<x
    #define pb push_back
    #define mp make_pair
    
    /** test **/
    
    #define Display(A, n, m) {                      \
        REP(i, n){                                  \
            REP(j, m) cout << A[i][j] << " ";       \
            cout << endl;                           \
        }                                           \
    }
    
    #define Display_1(A, n, m) {                    \
        REP_1(i, n){                                \
            REP_1(j, m) cout << A[i][j] << " ";     \
            cout << endl;                           \
        }                                           \
    }
    
    using namespace std;
    
    /** typedef **/
    
    typedef long long LL;
    
    /** Add - On **/
    
    const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
    const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
    const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };
    
    const int MOD = 1000000007;
    const int INF = 0x3f3f3f3f;
    const long long INFF = 1LL << 60;
    const double EPS = 1e-9;
    const double OO = 1e15;
    const double PI = acos(-1.0); //M_PI;
    int n,m,s,f;
    struct QAQ{
        int t,l,r;
    }a[211111];
    
    bool check(int x,int l,int r){
        if (x>=l&&x<=r) return true;
        return false;
    }
    int u;
    vector<char>vec;
    int main()
    {
        vec.clear();
        cin>>n>>m>>s>>f;
        u=1;
        REP(i,m) cin>>a[i].t>>a[i].l>>a[i].r;
        REP(i,m){
            int t,l,r;
            t=a[i].t;
            l=a[i].l;
            r=a[i].r;
            while (u<t){
                if (s<f) vec.push_back('R'),s++;
                if (s>f) vec.push_back('L'),s--;
                if (s==f) break;
                u++;
            }
            if (s==f) break;
            if (check(s,l,r)){
                vec.push_back('X');
            }
            else if (s<f&&check(s+1,l,r)){
                vec.push_back('X');
            }
            else if (s>f&&check(s-1,l,r)){
                vec.push_back('X');
            }
            else{
                if (s<f) vec.push_back('R'),s++;
                if (s>f) vec.push_back('L'),s--;
            }
            if (s==f) break;
            u++;
        }
        
        while (s!=f)
        {
            if (s<f) vec.push_back('R'),s++;
            if (s>f) vec.push_back('L'),s--;
        }
        
        REP(i,sz(vec)){
            cout<<vec[i];
        }
        cout<<endl;
        return 0;
    }
    -----------------------------

    C. Cupboard and Balloons

    ---

    将半径为r/2的圆球放进柜子里。

    首先考虑高为h的矩形区域,可证出两两并排向里放圆球最优。

    当放满h/r*2个球后,考虑剩下的空间。

    有三种可能,放1个,放2个,放3个。。

    ---

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    int main()
    {
        int r,h;
        int ans=0;
        cin>>r>>h;
        ans+=h/r*2;
        h=h%r;
        if (h>=sqrt(3)/2*r) ans+=3;
        else if (h>=1.0*r/2) ans+=2;
        else ans+=1;
        cout<<ans<<endl;
        return 0;
    }
    -----------------------------
    D. Xenia and Dominoes

    ---

    问3XN的格子有多少种骨牌摆放方案使其变成一个合理的游戏。

    若只考虑摆放方案,不考虑游戏是否合理(即空格是否可以移动),则问题转化成了传统的状态压缩dp。

    对于空格的x坐标。若x=1或x=3,可以发现无论骨牌怎样摆放,空格都是可以移动的。

    对于x=2。

    若空格右侧有空间(y+2<=n),则将空格右侧横放一个骨牌,再dp求出此时的方案数。

    若左侧有空间,则左侧横放骨牌,求出方案数。

    若左右都有空间,则将左右各方骨牌,总方案数减去此时的方案数。

    得出答案。

    ---

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    
    using namespace std;
    
    const int MAXN=16384;
    const int MOD=1000000007;
    char s[4][MAXN];
    int f[MAXN][8];
    int n,sx,sy;
    
    void input(){
        cin>>n;
        for (int i=1;i<=3;i++){
            cin>>(s[i]+1);
        }
    }
    void findDot(){
        for (int i=1;i<=3;i++){
            for (int j=1;j<=n;j++){
                if (s[i][j]=='O'){
                    sx=i;
                    sy=j;
                    return;
                }
            }
        }
    }
    int getBit(int j){
        int res=0;
        for (int i=1;i<=3;i++){
            if (s[i][j]!='.') res|=(1<<(3-i));
        }
        return res;
    }
    int getDP(int i,int k){
        if (k==0) return f[i-1][7];// 000 <- 111
        if (k==1) return f[i-1][6];// 001 <- 110
        if (k==2) return f[i-1][5];// 010 <- 101
        if (k==3) return (f[i-1][4]+f[i-1][7])%MOD;// 011 <- 100,111
        if (k==4) return f[i-1][3];// 100 <- 011
        if (k==5) return f[i-1][2];// 101 <- 010
        if (k==6) return (f[i-1][1]+f[i-1][7])%MOD;// 110 <- 001,111
        if (k==7) return ((f[i-1][0]+f[i-1][3])%MOD+f[i-1][6])%MOD;// 111 <- 000,011,110
        return -1;
    }
    int solve(){
        memset(f,0,sizeof(f));
        f[0][7]=1;
        for (int i=1;i<=n;i++){
            int k=getBit(i);
            for (int j=k;j<=7;j++){
                if ((j&k)==k){
                    f[i][j]=getDP(i,j&(~k));
                }
            }
        }
        return f[n][7];
    }
    
    int special(){
        int ans=0;
        bool lb=false,rb=false;
        if (sy-2>=1){
            if (s[2][sy-1]=='.'&&s[2][sy-2]=='.'){
                s[2][sy-1]=s[2][sy-2]='X';
                ans+=solve();
                s[2][sy-1]=s[2][sy-2]='.';
                lb=true;
            }
        }
        if (sy+2<=n){
            if (s[2][sy+1]=='.'&&s[2][sy+2]=='.'){
                s[2][sy+1]=s[2][sy+2]='X';
                ans+=solve();
                s[2][sy+1]=s[2][sy+2]='.';
                rb=true;
            }
        }
        if (lb&&rb){
            s[2][sy-1]=s[2][sy-2]='X';
            s[2][sy+1]=s[2][sy+2]='X';
            ans-=solve();
            s[2][sy-1]=s[2][sy-2]='.';
            s[2][sy+1]=s[2][sy+2]='.';
        }
        while (ans<0) ans+=MOD;
        ans%=MOD;
        return ans;
    }
    
    int main()
    {
        input();
        findDot();
        if (sx==2) cout<<special()<<endl;
        else cout<<solve()<<endl;
        return 0;
    }
    -----------------------------

    E. Xenia and Tree

    ---

    有一棵n个节点的树,根节点为红色,其它节点没有颜色,给出m个操作。

    1 x :将节点x染成红色

    2 x :输出节点x的距红色节点的最短距离

    平方分割法。令block=sqrt(m)。

    对于操作1,将待染色节点其加入队列que

    对于操作2,若队列元素个数>block,则利用队列里的红色节点做一次bfs,更新所有点到红色节点的最短距离。并输出dis[x];

    若元素个数不足block,则将dis[x]与点x到队列里所有的元素的距离做比较,并输出。

    求树上两点间的最短距离,用LCA实现。

    ---

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <queue>
    #include <stack>
    #include <cmath>
    using namespace std;
    const int maxn=211111;
    const int maxm=611111;
    const int INF=0x3f3f3f;
    //------最短路----------
    struct EdgeNode{
        int to;
        int next;
    };
    EdgeNode edges[maxm];
    int head[maxn],edge,n;
    void addedge(int u,int v){
        edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
    }
    void init(){
        memset(head,-1,sizeof(head));
        edge=0;
    }
    
    //---------MAIN---------------
    bool vis[maxn];
    int dis[maxn];
    queue<int>que;
    int block;
    void dfs(int u,int pa){
        if (pa==0) dis[u]=0;
        else dis[u]=dis[pa]+1;
        for (int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            if (v!=pa) dfs(v,u);
        }
    }
    void bfs(){
        memset(vis,0,sizeof(vis));
        while (!que.empty()){
            int u=que.front();
            que.pop();
            for (int i=head[u];i!=-1;i=edges[i].next){
                int v=edges[i].to;
                if (dis[u]+1<dis[v]){
                    dis[v]=dis[u]+1;
                    if (!vis[v]){
                        que.push(v);
                        vis[v]=true;
                    }
                }
            }
        }
    }
    //-----RMQ--------------
    int d[maxn][30];
    //元素从1编号到n
    void makeRmqIndex(int A[],int n){
        for(int i=1;i<=n;i++) d[i][0]=i;
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i+(1<<j)-1<=n;i++)
                d[i][j] = A[d[i][j-1]] < A[d[i+(1<<(j-1))][j-1]]? d[i][j-1]:d[i+(1<<(j-1))][j-1];
    }
    int rmqIndex(int L,int R,int A[]){
        int k=0;
        while ((1<<(k+1))<=R-L+1) k++;
        return A[d[L][k]]<A[d[R-(1<<k)+1][k]]? d[L][k]:d[R-(1<<k)+1][k];
    }
    //------LCA------------------------
    int deep[maxn];
    int E[maxn*2],R[maxn],D[maxn*2],mn;
    void dfs(int u,int p,int d){
        E[++mn]=u;
        D[mn]=d;
        R[u]=mn;
        for (int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            if (v==p) continue;
            dfs(v,u,d+1);
            E[++mn]=u;
            D[mn]=d;
        }
    }
    void getd(int u,int p,int w){
        deep[u]=w;
        for (int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            if (v==p) continue;
            getd(v,u,w+1);
        }
    }
    void LCA_init(){
        mn=0;
        memset(R,0,sizeof(R));
        dfs(1,-1,1);
        makeRmqIndex(D,mn);
        getd(1,-1,0);
    }
    int LCA(int u,int v){
        if (R[u]>=R[v]) return E[rmqIndex(R[v],R[u],D)];
        else return E[rmqIndex(R[u],R[v],D)];
    }
    int getDis(int u,int v){
        int lca=LCA(u,v);
        return deep[u]+deep[v]-deep[lca]*2;
    }
    
    int main()
    {
        int m;
        int x,y;
        scanf("%d%d",&n,&m);
        init();
        block=sqrt(m);
        for (int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        dfs(1,0);
        LCA_init();
        for (int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            if (x==1){
                que.push(y);
                dis[y]=0;
            }
            else if (x==2){
                if ((int)que.size()>block){
                    bfs();
                    printf("%d\n",dis[y]);
                }
                else{
                    int ans=dis[y];
                    int bg=0;
                    while (!que.empty()){
                        int q=que.front();
                        if (bg==0) bg=q;
                        else if (bg==q) break;
                        que.pop();
                        ans=min(ans, getDis(y,q) );
                        que.push(q);
                    }
                    printf("%d\n",ans);
                }
            }
        }
        return 0;
    }
    


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

    ---

    ---




  • 相关阅读:
    抉择
    PHP glob() 函数
    PHP之关闭网页错误提示
    PHP htmlentities() 函数
    PHP mysql_real_escape_string() 函数
    LFI & RFI & PHP封装协议之安全问题研究
    数据公钥加密和认证中的私钥公钥
    RSA算法
    APT攻防对抗
    安全参考
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681579.html
Copyright © 2011-2022 走看看