5.31
2015年百度之星程序设计大赛 - 初赛(1) 1001 超级赛亚ACMer
竟然看错题了。要哭了。
“如果百小度的战斗力大于对方,那么百小度就会轻易获胜,得不到锻炼并且骄傲起来,他以后的战斗力将保持在这个值,再也不会发生改变。”
贪心。每次打能持续爆超赛的人中最厉害的。能打过最后一个就好。
搞完读书笔记回来码。发现好像看错题并不影响过程。因为比我弱的我都是最后打的。
于是还是觉得自己当时码的没有错。然后就很费解为何会WA了。
最后发现好像是没有用LL嘛。//再也不相信爱情了
(不过怎么看都觉得自己的过程比拓神铖霸的烦好多)
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 typedef long long LL; 6 LL num[10005]; 7 8 int main(void) 9 { 10 int T;cin>>T; 11 for(int kase=1;kase<=T;kase++) 12 { 13 int n,m,k,index=0,ok=1; 14 scanf("%d%d%d",&n,&m,&k); 15 for(int i=1;i<=n;i++) scanf("%I64d",num+i); 16 sort(num+1,num+1+n); 17 while(index<n) 18 if(num[index+1]<=m) index++; 19 else break; 20 if(!index) {printf("Case #%d:\nmadan!\n",kase);continue;} 21 LL tem=num[index]; 22 while(index<n) 23 { 24 ok=0; 25 for(int i=index;i<n;i++) 26 if(num[i+1]<=tem+max(0,k)) {ok=1;index=i+1;} 27 else break; 28 if(!ok) break; 29 tem=num[index];k--; 30 } 31 if(!ok) printf("Case #%d:\nmadan!\n",kase); 32 else printf("Case #%d:\nwhy am I so diao?\n",kase); 33 } 34 return 0; 35 }
下午又玩了一场百度之星。然而只做了一个。
2015年百度之星程序设计大赛 - 初赛(2) 1003 棋盘占领
每次把新增的黑点放进队列,检查它四周有没有能被黑化的白点。
1 # include <iostream> 2 # include <cstdio> 3 # include <queue> 4 # include <cstring> 5 using namespace std; 6 int map[501][501],MOVE[4][2]={{-1,0},{1,0},{0,1},{0,-1}}; 7 8 int main(void) 9 { 10 int T;cin>>T; 11 for(int kase=1;kase<=T;kase++) 12 { 13 int n,m,g; scanf("%d%d%d",&n,&m,&g); 14 int ans=g; 15 memset(map,0,sizeof(map)); 16 queue< pair<int,int> > q1,q2; 17 for(int i=0;i<g;i++) 18 { 19 int x,y;scanf("%d%d",&x,&y); 20 if(map[x][y]) ans--; 21 else{ map[x][y]=1; q1.push(make_pair(x,y)); } 22 } 23 while(!q1.empty()) 24 { 25 int x=q1.front().first,y=q1.front().second; q1.pop(); 26 for(int i=0;i<4;i++) 27 if(x+MOVE[i][0]>=1&&x+MOVE[i][0]<=n&&y+MOVE[i][1]>=0&&y+MOVE[i][1]<=m&&!map[x+MOVE[i][0]][y+MOVE[i][1]]) 28 q2.push(make_pair(x+MOVE[i][0],y+MOVE[i][1])); 29 while(!q2.empty()) 30 { 31 int a=q2.front().first,b=q2.front().second; q2.pop(); 32 int ok=0; 33 if(a>1&&b>1&&map[a][b-1]&&map[a-1][b]) ok=1; 34 else if(a>1&&b<m&&map[a-1][b]&&map[a][b+1]) ok=1; 35 else if(a<n&&b>1&&map[a+1][b]&&map[a][b-1]) ok=1; 36 else if(a<n&&b<m&&map[a+1][b]&&map[a][b+1]) ok=1; 37 if(ok) {map[a][b]=1; q1.push(make_pair(a,b));ans++;} 38 } 39 } 40 printf("Case #%d:\n%d\n",kase,ans); 41 } 42 return 0; 43 }
后面出了点问题。搞不定。明天再看吧。
6.1
儿童节快乐。
2015年百度之星程序设计大赛 - 初赛(2) 1002 连接的管道
昨天被这个题整的蛮苦的。
因为第一眼看到觉得是最小生成树。于是最先写了。
当时大部分人应该是先写dp。然而并不会。
不知道哪个快。写的Prim。
写完第一发随手开爆M了。当时用的向量存图。
改成结构体存图。继续爆M。
后来发现再存一次边是多余的。然后又爆T了。就写别的去了。
然而后来去hdu上补题的时候。没改过的代码竟然过了。
可能hdu和BC的机子不一样吧TAT。
多跑了几次。有出现.9s+的情况。在比赛的时候很容易跪吧。
1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 # include <cstring> 5 # include <queue> 6 using namespace std; 7 # define CLR(x) memset(x,0,sizeof(x)) 8 typedef long long LL; 9 int map[1001][1001],MOVE[4][2]={-1,0,1,0,0,-1,0,1}; 10 bool vis[1001][1001]; 11 12 struct node 13 { 14 int i,j,value; 15 friend bool operator < (node a, node b) 16 { 17 return a.value > b.value; 18 } 19 }; 20 21 int main(void) 22 { 23 int T;cin>>T; 24 for(int kase=1;kase<=T;kase++) 25 { 26 int N,M;scanf("%d%d",&N,&M); 27 for(int i=1;i<=N;i++) 28 for(int j=1;j<=M;j++) 29 scanf("%d",&map[i][j]); 30 priority_queue < node > q; 31 LL ans=0; CLR(vis); vis[1][1]=1; 32 node x; 33 x.i=1;x.j=2;x.value=abs(map[1][1]-map[1][2]); q.push(x); 34 x.i=2;x.j=1;x.value=abs(map[1][1]-map[2][1]); q.push(x); 35 while(!q.empty()) 36 { 37 int tem=q.top().value,toi=q.top().i,toj=q.top().j; q.pop(); 38 if(!vis[toi][toj]) 39 { 40 vis[toi][toj]=1; ans+=tem; 41 for(int i=0;i<4;i++) 42 if(toi+MOVE[i][0]>=1&&toi+MOVE[i][0]<=N&&toj+MOVE[i][1]>=1&&toj+MOVE[i][1]<=M&&!vis[toi+MOVE[i][0]][toj+MOVE[i][1]]) 43 { 44 x.i=toi+MOVE[i][0];x.j=toj+MOVE[i][1]; 45 x.value=abs(map[toi][toj]-map[x.i][x.j]); q.push(x); 46 } 47 } 48 } 49 printf("Case #%d:\n%I64d\n",kase,ans); 50 } 51 return 0; 52 }
不知道Kruskal会不会快一些。于是推了重写。
存图的时候又爆M了。但是看见一个别人的程序。数组开的都比我大。却没有爆M。好费解。
结果是跑的要比Prim快一些拉。
当时笔记上记的是边多用Prim。但是对于多与少并没有概念QAQ
# include <iostream> # include <cstdio> # include <cmath> # include <algorithm> using namespace std; # define I(x) ( ( x/M ) + ( x%M ? 1:0 ) ) # define J(x) ( x%M ? x%M : M ) # define ID(i,j) ( ( i-1 ) * M + j ) # define maxn 1000001 typedef long long LL; int h[maxn],pa[maxn]; int fa(int x) { return pa[x]==x?x:pa[x]=fa(pa[x]); } struct node { int from,to,value; } edge[2*maxn]; bool cmp(node a,node b) { return a.value<b.value; } int main(void) { int T;cin>>T; for(int kase=1;kase<=T;kase++) { int N,M;scanf("%d%d",&N,&M); for(int i=1;i<=N*M;i++) { pa[i]=i; scanf("%d",h+i); } int num=0; for(int i=1;i<N;i++) for(int j=1;j<=M;j++) { num++; edge[num].from=ID(i,j);edge[num].to=ID(i+1,j); edge[num].value=abs( h[edge[num].from]-h[edge[num].to] ); } for(int j=1;j<M;j++) for(int i=1;i<=N;i++) { num++; edge[num].from=ID(i,j);edge[num].to=ID(i,j+1); edge[num].value=abs( h[edge[num].from]-h[edge[num].to] ); } sort(edge+1,edge+1+num,cmp); LL ans=0; int cnt=0; for(int i=1;i<=num;i++) if(cnt==M*N-1) break; else if(fa(edge[i].from)!=fa(edge[i].to)) { cnt++; ans+=edge[i].value; pa[fa(edge[i].to)]=pa[fa(edge[i].from)]; } printf("Case #%d:\n%I64d\n",kase,ans); } return 0; }
6.2
想补题的。码了好久。吃一发T。
偏偏是这种忙的时候。感觉又浪费时间了。
心累。不码了。
大概过了一个多小时,想想反正浪费了那么多时间了。再浪费一些吧。破罐子破摔了。
2015年百度之星程序设计大赛 - 初赛(1) 1002 找连续数
先贴一个T掉的sb线段树。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 # include <cstring> 5 using namespace std; 6 int num[10001],cnt[1001]; 7 8 struct node 9 { 10 int a,b,max,min; 11 } tree[10001*4]; 12 13 void maketree(int i,int a,int b) 14 { 15 tree[i].a=a;tree[i].b=b; 16 if(a==b) 17 { 18 tree[i].max=tree[i].min=num[a]; 19 return; 20 } 21 maketree(2*i,a,(a+b)/2); 22 maketree(2*i+1,(a+b)/2+1,b); 23 tree[i].max=max(tree[2*i].max,tree[2*i+1].max); 24 tree[i].min=min(tree[2*i].min,tree[2*i+1].min); 25 return; 26 } 27 28 int MAX(int i,int a,int b) 29 { 30 if(a<=tree[i].a&&tree[i].b<=b) return tree[i].max; 31 if(b<=(tree[i].a+tree[i].b)/2) return MAX(2*i,a,b); 32 if(a>=(tree[i].a+tree[i].b)/2+1) return MAX(2*i+1,a,b); 33 return max(MAX(2*i,a,b),MAX(2*i+1,a,b)); 34 } 35 36 int MIN(int i,int a,int b) 37 { 38 if(a<=tree[i].a&&tree[i].b<=b) return tree[i].min; 39 if(b<=(tree[i].a+tree[i].b)/2) return MIN(2*i,a,b); 40 if(a>=(tree[i].a+tree[i].b)/2+1) return MIN(2*i+1,a,b); 41 return min(MIN(2*i,a,b),MIN(2*i+1,a,b)); 42 } 43 44 int main(void) 45 { 46 int n,m; scanf("%d%d",&n,&m); 47 for(int i=1;i<=n;i++) scanf("%d",num+i); 48 maketree(1,1,n); 49 printf("Case #1:\n"); 50 while(m--) 51 { 52 int k,ans=0;scanf("%d",&k); 53 for(int i=1;i+k-1<=n;i++) 54 { 55 int Max=MAX(1,i,i+k-1),Min=MIN(1,i,i+k-1); 56 if(Max-Min==k-1) 57 { 58 int ok=1; 59 memset(cnt,0,sizeof(cnt)); 60 for(int j=i;j<i+k;j++) cnt[num[j]-Min]++; 61 for(int j=0;j<k;j++) 62 if(cnt[j]>1) {ok=0;break;} 63 if(ok) ans++; 64 } 65 } 66 printf("%d\n",ans); 67 } 68 return 0; 69 }
看见最值就想写线段树阿。誰知道会这样呢。
写了个暴力。交了十几次。竟然过了几次。(上面那个一次都没过)
抄了个优化。过了。然而。不开心。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 using namespace std; 5 int num[10001]={0},cnt[1001]; 6 7 int main(void) 8 { 9 int n,m; scanf("%d%d",&n,&m); 10 for(int i=1;i<=n;i++) scanf("%d",num+i); 11 printf("Case #1:\n"); 12 while(m--) 13 { 14 int k,ans=0;scanf("%d",&k); 15 for(int i=1;i+k-1<=n;i++) 16 { 17 int MAX,MIN; 18 if(i!=1&&num[i-1]!=MAX&&num[i-1]!=MIN) 19 { 20 if(num[i+k-1]>MAX) MAX=num[i+k-1]; 21 if(num[i+k-1]<MIN) MIN=num[i+k-1]; 22 } 23 else 24 { 25 MAX=num[i],MIN=num[i]; 26 for(int j=1;j<k;j++) 27 { 28 if(MAX<num[i+j]) MAX=num[i+j]; 29 if(MIN>num[i+j]) MIN=num[i+j]; 30 } 31 } 32 if(MAX-MIN==k-1) 33 { 34 int ok=1; 35 memset(cnt,0,sizeof(cnt)); 36 for(int j=i;j<i+k;j++) cnt[num[j]-MIN]++; 37 for(int j=0;j<k;j++) 38 if(cnt[j]>1) {ok=0;break;} 39 if(ok) ans++; 40 } 41 } 42 printf("%d\n",ans); 43 } 44 return 0; 45 }
6.3
2015年百度之星程序设计大赛 - 初赛(1) 1005 三阶魔方
当时打第一场的时候发现都不会。这道题少有人交。但还是选择了码这道。
一开始数据出错了。但大部分的人是觉得麻烦不想写吧。
记得刚进A协的时候。司老大讲了置换。那时候做了一个好烦的置换。
写了好几天。写的又丑又长。而且Uva还出错了。
找司老大帮忙。他叫我重新看置换有没写错。后来找不出错就搁置在那。
后来过了几天再交了一次就过了。好开心的。
比赛的时候WA了。后来发现是只考虑了块的位置。忘记了方向。
(还挺喜欢魔方的。好惭愧。娱乐向。非竞速党。)
在贴吧看见一个帖子。乌木老师讲了盲拧中的色向。然而并不了解色向和的计算。
Link:http://tieba.baidu.com/p/3795808536
于是选择了蠢蠢的办法。就是给54个面标号……
写完代码又是丑丑的。不知道怎么标号会好看些阿。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 using namespace std; 5 typedef unsigned long long ULL; 6 int cube[54],cpy[54],cnt[54]; 7 8 ULL gcd(ULL x,ULL y) 9 { 10 return (x%y==0)? y : gcd(y,x%y); 11 } 12 13 ULL lcm(ULL x,ULL y) 14 { 15 return (x*y)/gcd(x,y); 16 } 17 18 void change(int x1,int x2,int x3,int x4) 19 { 20 cube[x1]=cpy[x2];cube[x2]=cpy[x3];cube[x3]=cpy[x4];cube[x4]=cpy[x1]; 21 return; 22 } 23 24 void move(char c) 25 { 26 if(c=='U'){change(18,24,26,20);change(21,25,23,19);change(0,9,29,38);change(1,10,28,37);change(2,11,27,36);} 27 if(c=='R'){change(10,12,16,14);change(9,15,17,11);change(20,2,53,35);change(23,5,50,32);change(26,8,47,29);} 28 if(c=='F'){change(1,3,7,5);change(0,6,8,2);change(24,42,53,9);change(25,39,52,12);change(26,36,51,15);} 29 if(c=='D'){change(53,51,45,47);change(52,48,46,50);change(6,44,35,15);change(7,43,34,16);change(8,42,33,17);} 30 if(c=='L'){change(36,38,44,42);change(37,41,43,39);change(24,27,45,6);change(21,30,48,3);change(18,33,51,0);} 31 if(c=='B'){change(27,29,35,33);change(30,28,32,34);change(18,11,47,44);change(19,14,46,41);change(20,17,45,38);} 32 memcpy(cpy,cube,sizeof(cpy)); 33 return; 34 } 35 36 int main(void) 37 { 38 int T;cin>>T;getchar(); 39 for(int kase=1;kase<=T;kase++) 40 { 41 for(int i=0;i<54;i++) 42 cube[i]=cpy[i]=i; 43 char s[105];gets(s); 44 int len=strlen(s); 45 for(int i=0;i<len;i++) if(s[i]=='\''||s[i]=='2') {char t=s[i];s[i]=s[i-1];s[i-1]=t;} 46 for(int i=0;i<len;) 47 if(s[i]=='\'') {move(s[i+1]);move(s[i+1]);move(s[i+1]);i+=2;} 48 else if(s[i]=='2') {move(s[i+1]);move(s[i+1]);i+=2;} 49 else{ move(s[i]); i++;} 50 memset(cpy,0,sizeof(cpy)); 51 memset(cnt,0,sizeof(cnt)); 52 for(int i=0;i<54;i++) 53 if(!cpy[i]) 54 { 55 int t=i,k=0; 56 while(!cpy[t]) { k++; cpy[t]=1; t=cube[t];} 57 cnt[k]=1; 58 } 59 ULL ans=1; 60 for(int i=1;i<=54;i++) if(cnt[i]) ans=lcm(ans,i); 61 printf("Case #%d:\n%I64d\n",kase,ans); 62 } 63 return 0; 64 }
6.4
补一个题。WA一晚。再战。
6.5
TAT 忙 一天没码程序噜。
6.6
2015年百度之星程序设计大赛 - 初赛(1) 1004 KPI
拖了两天的题目。
郏老大曾经曰过:动态维护第k值这种千古经典问题一向有很多解决办法:线段树、树状数组、平衡树等……
当年补Black Box的时候 用的两个堆对顶。
学了线段树和树状数组后想试试看拉。
先离散化。再用二分法查询。
一开始以为二分写错了。后来发现离散化就写错了- -
以前做过两个离散化。都是那种把原象映射到象后不需要再用到原象的。(不知道怎么表达 大概是这个意思)
这个需要再映射回去。不敢再用map了。T怕了。
就去抄了一个离散化。还是二分查找的。
# include <iostream> # include <cstdio> # include <cstring> # include <queue> # include <algorithm> using namespace std; int a[10001],b[10001],c[10001]; int lowbit(int s) { return s&(-s); } void add(int i,int x) { while(i<=10000){c[i]+=x;i+=lowbit(i);} return; } int sum(int i) { int ans=0; while(i>0) {ans+=c[i];i-=lowbit(i);} return ans; } int search(int x) { int L=1,R=10000,m; while(L<R) { m=(L+R)/2; if(sum(m)<x) L=m+1; else R=m; } return L; } int main(void) { int n,kase=0; while((scanf("%d",&n))!=EOF) { memset(c,0,sizeof(c)); queue <int> q,fro; int cnt=0; for(int i=0;i<n;i++) { char s[10]; scanf("%s",s); if(s[0]=='i') { cnt++; scanf("%d",a+cnt); b[cnt]=a[cnt]; q.push(1); } else if(s[0]=='q') q.push(0); else q.push(-1); } sort(b+1,b+1+cnt); int m=0,tem=0; printf("Case #%d:\n",++kase); while(!q.empty()) { int ord=q.front();q.pop(); if(ord==1) { tem++; m++; int x=lower_bound(b+1,b+cnt+1,a[tem])-b; add(x,1); fro.push(x); } if(ord==0) printf("%d\n",b[search(m/2+1)]); if(ord==-1) { int x=fro.front(); fro.pop(); add(x,-1); m--; } } } return 0; }
然而无意之间学习到了名为set大法的神奇玩意儿。
set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还得确保根节点的左子树的高度与有字数的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。
平衡二叉检索树的检索使用中序遍历算法,检索效率高于vector、deque、和list的容器。另外,采用中序遍历算法可将键值由小到大遍历出来,所以,可以理解为平衡二叉检索树在插入元素时,就会自动将元素按键值从小到大的顺序排列。
构造set集合的主要目的是为了快速检索,使用set前,需要在程序头文件中包含声明“#include<set>”。
虽然不懂红黑树是什么。但是看起来好厉害的样子。忍不住抄了一个set大法。
(一直以来只知道用set来去重真是呵呵哒 迭代器什么的还是第一次用呢)
# include <iostream> # include <cstdio> # include <queue> # include <set> using namespace std; int main(void) { int n,kase=0; while((scanf("%d",&n))!=EOF) { printf("Case #%d:\n",++kase); queue <int> q; set <int> s1,s2; for(int i=0;i<n;i++) { char s[10]; scanf("%s",s); if(s[0]=='i') { int x; scanf("%d",&x); q.push(x); if(!s1.empty()&&x<*s1.rbegin()) { s1.insert(x); if(s1.size()>s2.size()) {s2.insert(*s1.rbegin());s1.erase(*s1.rbegin());} } else { s2.insert(x); if(s2.size()-s1.size()>1) {s1.insert(*s2.begin());s2.erase(*s2.begin());} } } else if(s[0]=='q') printf("%d\n",*s2.begin()); else { int x=q.front(); q.pop(); if(s1.count(x)) { s1.erase(x); if(s2.size()-s1.size()>1) {s1.insert(*s2.begin());s2.erase(*s2.begin());} } else { s2.erase(x); if(s1.size()>s2.size()) {s2.insert(*s1.rbegin());s1.erase(*s1.rbegin());} } } } } return 0; }
2015年百度之星程序设计大赛 - 初赛(1) 1003 序列变换
感觉二分一直写不好。特别是收敛到边界的时候就弄错。
于是又写了一个不麻烦的二分+贪心。
然而并不知道为什么可以贪 - -b
# include <iostream> # include <cstdio> # include <cstring> # include <algorithm> using namespace std; int N,a[100001],b[100001]; bool judge(int x) { memcpy(b,a,sizeof(a)); b[0]=b[0]-x; for(int i=1;i<N;i++) { if(b[i]>b[i-1]) b[i]=max(b[i-1]+1,b[i]-x); else if(b[i]+x>b[i-1]) b[i]=b[i-1]+1; else return false; } return true; } int main(void) { int T;cin>>T; for(int kase=1;kase<=T;kase++) { scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d",a+i); int L=0,R=1000000,mid; while(L<R) { mid=(L+R)/2; if(judge(mid)) R=mid; else L=mid+1; } printf("Case #%d:\n%d\n",kase,L); } return 0; }
前两周搞了会儿百度之星。虽然没出几个题并且早早的被淘汰了。
但是觉得偶尔打打这种。见见世面。也算有点帮助吧。
能补的稍微补了下。剩下的就不管了。
积分制取消了哈哈哈哈哈。
下周要考四级了。要考近代史了。
好!怕!怕!