[COCI 2009/2010 – Constest #7 BAKICE]排序、模拟

【题目地址】http://evaluator.hsin.hr/login.php?redirect=index.php
【题目大意】
。。。不想写了,等下有时间或许会补一下。
【算法分析】
看规模觉得很假。
于是直接暴力把所有点对取出来按距离排序。
然后贪心的取。
其实也不叫贪心了,应该说按题目那样模拟。
然后~,Orz,居然0MS AC了。。。
【CODE】
#include #include #include #include #define sqr(x) ((x)*(x))
const int N=105;
const int INF=1000000000;
struct Queue{int x[N*N],y[N*N],t;}L,R;
struct edge{int x,y;}g[4000000];
bool v[N*N],Break[N*N];
int m,n,e,ans,link[N*N];
char c[N][N];

inline int dis(int i,int j){return sqr(L.x[i]-R.x[j])+sqr(L.y[i]-R.y[j]);}
inline int cmp(const void *x,const void *y){
return dis( ((edge*)x)->x, ((edge*)x)->y )
– dis( ((edge*)y)->x, ((edge*)y)->y );
}

void init(){
L.t=R.t=e=0;
int i,j;
scanf("%d%d",&m,&n);
for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
for (;c[i][j]!=’.’ && c[i][j]!=’X’ && c[i][j]!=’L’;c[i][j]=getchar());
for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
if (c[i][j]==’X’){
L.t++;
L.x[L.t]=i;
L.y[L.t]=j;
}
else if (c[i][j]==’L’){
R.t++;
R.x[R.t]=i;
R.y[R.t]=j;
}
for (i=1;i<=L.t;i++)
for (j=1;j<=R.t;j++){
e++;
g[e].x=i; g[e].y=j;
}
qsort(&g[1],e,sizeof(edge),cmp);
}

void solve(){
memset(v,false,sizeof(v));
memset(link,0,sizeof(link));
memset(Break,false,sizeof(Break));
ans=0;
int i,j,k;
for (k=1;k<=e;k++){
i=g[k].x; j=g[k].y;
if (v[i]) continue;
if (!v[i] && !link[j]){
v[i]=true;
link[j]=i;
continue;
}
if (dis(i,j)==dis(link[j],j)){
if (!Break[j]) ans++;
Break[j]=true;
v[i]=true;
}
}
printf("%dn",ans);
}

int main(){
// freopen("bakice.in","r",stdin);
// freopen("bakice.out","w",stdout);
init();
solve();
}

[COCI 2009/2010 – Constest #7 COKOLADA]对二进制数的理解

【题目链接】http://evaluator.hsin.hr/login.php?redirect=index.php
【题目大意】
给出一个尺寸N。
你需要取一个2^k (k是任你选的)的巧克力出来,然后切若干刀(每刀把一个巧克力切开成两半一样大小的)
最终在其中取出若干个块巧克力,使得加起来的尺寸等于N。
最终输出2^k和切得刀数。
在保证2^k最小的前提下,切刀数要最少。
【算法分析】
同属于被秒杀题= =
假如N=2^k,那么直接输出  2^k 0
否则输出最小的一个k满足,N<2^k (用log2求就可以了),
然后输出将n变成二进制以后从个位数上去的第一个“1”和k的差即可。
【其它】
YY一下就懂了。
【CODE】
#include #include #include int n,LG,i;
scanf("%d",&n);
LG=(int)(log(n)/log(2)+1e-7);
if (1< else{
LG++;
i=0;
while (n%2==0){
i++;
n/=2;
}
printf("%d %dn",1< }
}

[COCI 2009/2010 – Constest #7 SPAVANAC]水题

【题目地址】http://evaluator.hsin.hr/login.php?redirect=index.php
【题目大意】
给出一个24小时制的时间,让你输出它的前45分钟时多少。
【算法分析】
类a-b problems
【其它】
。。。其实我不想写的,但是为了完整性,还是写一下。。。
【CODE】
#include int main(){
int H,M;
scanf("%d%d",&H,&M);
M-=45;
if (M<0){M+=60; H--;}
if (H<0) H+=24;
printf("%d %dn",H,M);
}

[BOI2010 bins]一个桶

【BOI链接】http://www.ut.ee/boi/
【题目大意】
按顺序给出n<=20000个箱子,他们的尺寸m<=1000。
求一个最大的k,使得前k个和第k+1个到2*k个箱子之间能一一匹配。
能匹配的定义是i∈[1,k] 且 j∈[k+1,2*k] 同时Size[i]【算法分析】
因为m<=1000,开一个1000的桶,然后从k从n/2开始枚举下来,维护一下。
由于O(nm)都不会超时,直接每次都暴力判断就好了。
【CODE】
#include #include #include int a[20001],t1[1001],t2[1001];

bool flag(){
int num1=0,num2=0,i;
for (i=1;i<=m;i++){
if (num1 num1+=t1[i];
num2+=t2[i];
if (num1 }
return true;
}

int main(){
int i,k,ans=0;
memset(t1,0,sizeof(t1));
memset(t2,0,sizeof(t2));
freopen("bins.in","r",stdin);
freopen("bins.out","w",stdout);
scanf("%d%d",&m,&n);
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
k=n/2;
for (i=1;i<=k;i++) t1[a[i]]++;
for (i=k+1;i<=2*k;i++) t2[a[i]]++;
for (k=n/2;k>=0;k–){
if (flag()){
ans=k;
break;
}
if (!k) break;
t1[a[k]]–;
t2[a[k]]++;
t2[a[2*k]]–;
t2[a[2*k-1]]–;
}
printf("%dn",ans);
}

[BOI2010 pcb]贪心、平衡树

【题目和数据下载地址】http://www.ut.ee/boi/
【题目大意】
给定n条电线(Ai,Bi),其中A点都在一矩形箱子的上方,B点都在矩形箱子的下方。
其中Ai和Bi分别表示他们的横坐标。
然后这些电线交叉的话会短路,问至少要弄多少层(每层之间完全隔开),才能把这些电线全连上而又不短路。
数据保证Ai和Bi是2*n个不相同的整数。

【算法分析】
显然,假如对于一对电线(i,j),Ai我们先对电线按Ai从小到大排序,那么就变成了求把用最少的递增数列,把这个Bi数列全部分出来。
显然,假如Bi但是N<=100000。显然很难通过,因为边都有可能超过1000 0000。
于是我们可以贪心一下。
对于每个递增序列,记录它的最后一个就可以了,因为前面的已经和扩展无关了。
然后每一次对于一个Bi,在开了的ans个递增序列里找一个这样的序列i,满足:
Max(End[i]  :End[i]然后将Bi插到那个序列后面去。
遇过找不到这样一个序列,那么就新开一个序列,ans++,End[ans]=Bi。
最后输出ans即可。
然后对于上面那个找Max(End[i]  :End[i]【CODE】
#include #include #include const int N=100005;
struct Point{int x,y;}a[N];
int n,ans;

struct SBT_Type{
struct Node{int l,r,key,s;}tr[N*3];
int tot,root;
void update(int p){if (p) tr[p].s=tr[tr[p].l].s+tr[tr[p].r].s+1;}
int max(int x,int y){return x>y?x:y;}

void left(int &p){
int k=tr[p].r;
tr[p].r=tr[k].l;
tr[k].l=p;
update(p);
update(k);
p=k;
}

void right(int &p){
int k=tr[p].l;
tr[p].l=tr[k].r;
tr[k].r=p;
update(p);
update(k);
p=k;
}

void repair(int &p){
if (!p) return;
bool flag=false;
if (tr[tr[tr[p].l].l].s>tr[tr[p].r].s){
right(p);
flag=true;
}
if (tr[tr[tr[p].l].r].s>tr[tr[p].r].s){
left(tr[p].l);
right(p);
flag=true;
}
if (tr[tr[tr[p].r].r].s>tr[tr[p].l].s){
left(p);
flag=true;
}
if (tr[tr[tr[p].r].l].s>tr[tr[p].l].s){
right(tr[p].r);
left(p);
flag=true;
}
if (flag){
repair(tr[p].l);
repair(tr[p].r);
repair(p);
}
}

int del(int &p,int key){
tr[p].s–;
if (key int res=tr[p].key;
if (!tr[p].l || !tr[p].r) p=tr[p].l+tr[p].r;
else tr[p].key=del(tr[p].l,0x7FFFFFFF);
return res;
}
if (key else return del(tr[p].r,key);
}

void ins(int &p,int key){
if (!p){
p=++tot;
tr[p].l=tr[p].r=0; tr[p].s=1; tr[p].key=key;
return;
}
tr[p].s++;
if (key else ins(tr[p].r,key);
repair(p);
}

int Find(int p,int key){
if (!p) return -0x7FFFFFFF;
if (key>tr[p].key) return max(tr[p].key,Find(tr[p].r,key));
return Find(tr[p].l,key);
}
}SBT;

int cmp(const void *x,const void *y){
return ((Point*)x)->x-((Point*)y)->x;
}

int main(){
freopen("pcb.in","r",stdin);
freopen("pcb.out","w",stdout);
int i,tmp;
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
qsort(a+1,n,sizeof(Point),cmp);
SBT.tot=SBT.root=ans=0;
for (i=1;i<=n;i++){
tmp=SBT.Find(SBT.root,a[i].y);
if (tmp==-0x7FFFFFFF){
ans++;
SBT.ins(SBT.root,a[i].y);
}
else{
SBT.del(SBT.root,tmp);
SBT.ins(SBT.root,a[i].y);
}
}
printf("%dn",ans);
}