您的位置:首页 > 其它

Codeforces Round #199 (Div. 2)

2013-09-13 11:45 204 查看
-----------------------------

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


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

---

---
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: