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;
}


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

---

---




posted on 2013-09-13 11:45  电子幼体  阅读(109)  评论(0编辑  收藏  举报

导航