第三周 5.31-6.6

5.31

 

2015年百度之星程序设计大赛 - 初赛(1) 1001 超级赛亚ACMer

竟然看错题了。要哭了。

“如果百小度的战斗力大于对方,那么百小度就会轻易获胜,得不到锻炼并且骄傲起来,他以后的战斗力将保持在这个值,再也不会发生改变。

贪心。每次打能持续爆超赛的人中最厉害的。能打过最后一个就好。

 

搞完读书笔记回来码。发现好像看错题并不影响过程。因为比我弱的我都是最后打的。

于是还是觉得自己当时码的没有错。然后就很费解为何会WA了。

最后发现好像是没有用LL嘛。//再也不相信爱情了

(不过怎么看都觉得自己的过程比拓神铖霸的烦好多)

第三周 5.31-6.6
 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 }
Aguin

 

下午又玩了一场百度之星。然而只做了一个。

2015年百度之星程序设计大赛 - 初赛(2) 1003 棋盘占领

每次把新增的黑点放进队列,检查它四周有没有能被黑化的白点。

第三周 5.31-6.6
 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 }
Aguin

 

后面出了点问题。搞不定。明天再看吧。

 

6.1

 

儿童节快乐。

2015年百度之星程序设计大赛 - 初赛(2) 1002 连接的管道

昨天被这个题整的蛮苦的。

因为第一眼看到觉得是最小生成树。于是最先写了。

当时大部分人应该是先写dp。然而并不会。

不知道哪个快。写的Prim。

写完第一发随手开爆M了。当时用的向量存图。

改成结构体存图。继续爆M。

后来发现再存一次边是多余的。然后又爆T了。就写别的去了。

 

然而后来去hdu上补题的时候。没改过的代码竟然过了。

可能hdu和BC的机子不一样吧TAT。

多跑了几次。有出现.9s+的情况。在比赛的时候很容易跪吧。

第三周 5.31-6.6
 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 }
Aguin

 

不知道Kruskal会不会快一些。于是推了重写。

存图的时候又爆M了。但是看见一个别人的程序。数组开的都比我大。却没有爆M。好费解。

结果是跑的要比Prim快一些拉。

当时笔记上记的是边多用Prim。但是对于多与少并没有概念QAQ

第三周 5.31-6.6
# 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;

}
Aguin

 

6.2

想补题的。码了好久。吃一发T。

偏偏是这种忙的时候。感觉又浪费时间了。

心累。不码了。

 

 

大概过了一个多小时,想想反正浪费了那么多时间了。再浪费一些吧。破罐子破摔了。

2015年百度之星程序设计大赛 - 初赛(1) 1002 找连续数

先贴一个T掉的sb线段树。

第三周 5.31-6.6
 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 }
Aguin

看见最值就想写线段树阿。誰知道会这样呢。

写了个暴力。交了十几次。竟然过了几次。(上面那个一次都没过)

抄了个优化。过了。然而。不开心。

第三周 5.31-6.6
 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 }
Aguin

 

6.3

2015年百度之星程序设计大赛 - 初赛(1) 1005 三阶魔方

当时打第一场的时候发现都不会。这道题少有人交。但还是选择了码这道。

一开始数据出错了。但大部分的人是觉得麻烦不想写吧。

 

记得刚进A协的时候。司老大讲了置换。那时候做了一个好烦的置换。

写了好几天。写的又丑又长。而且Uva还出错了。

找司老大帮忙。他叫我重新看置换有没写错。后来找不出错就搁置在那。

后来过了几天再交了一次就过了。好开心的。

 

比赛的时候WA了。后来发现是只考虑了块的位置。忘记了方向。

(还挺喜欢魔方的。好惭愧。娱乐向。非竞速党。)

 

在贴吧看见一个帖子。乌木老师讲了盲拧中的色向。然而并不了解色向和的计算。

Link:http://tieba.baidu.com/p/3795808536

于是选择了蠢蠢的办法。就是给54个面标号……

写完代码又是丑丑的。不知道怎么标号会好看些阿。

第三周 5.31-6.6
 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 }
Aguin

 

6.4

补一个题。WA一晚。再战。

 

6.5

TAT 忙 一天没码程序噜。

 

6.6

2015年百度之星程序设计大赛 - 初赛(1) 1004 KPI

拖了两天的题目。

郏老大曾经曰过:动态维护第k值这种千古经典问题一向有很多解决办法:线段树、树状数组、平衡树等……

当年补Black Box的时候 用的两个堆对顶。

学了线段树和树状数组后想试试看拉。

先离散化。再用二分法查询。

一开始以为二分写错了。后来发现离散化就写错了- -

以前做过两个离散化。都是那种把原象映射到象后不需要再用到原象的。(不知道怎么表达 大概是这个意思)

这个需要再映射回去。不敢再用map了。T怕了。

就去抄了一个离散化。还是二分查找的。

第三周 5.31-6.6
# 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;

}
Aguin

 

然而无意之间学习到了名为set大法的神奇玩意儿。

 

        set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还得确保根节点的左子树的高度与有字数的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。

        平衡二叉检索树的检索使用中序遍历算法,检索效率高于vector、deque、和list的容器。另外,采用中序遍历算法可将键值由小到大遍历出来,所以,可以理解为平衡二叉检索树在插入元素时,就会自动将元素按键值从小到大的顺序排列。

        构造set集合的主要目的是为了快速检索,使用set前,需要在程序头文件中包含声明“#include<set>”。

 

虽然不懂红黑树是什么。但是看起来好厉害的样子。忍不住抄了一个set大法。

(一直以来只知道用set来去重真是呵呵哒 迭代器什么的还是第一次用呢)

第三周 5.31-6.6
# 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;

}
Aguin

 

2015年百度之星程序设计大赛 - 初赛(1) 1003 序列变换

感觉二分一直写不好。特别是收敛到边界的时候就弄错。

于是又写了一个不麻烦的二分+贪心。

然而并不知道为什么可以贪 - -b

第三周 5.31-6.6
# 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;

}
Aguin

 

前两周搞了会儿百度之星。虽然没出几个题并且早早的被淘汰了。

但是觉得偶尔打打这种。见见世面。也算有点帮助吧。

能补的稍微补了下。剩下的就不管了。

 

积分制取消了哈哈哈哈哈。

 

下周要考四级了。要考近代史了。

好!怕!怕!

你可能感兴趣的:(第三周 5.31-6.6)