博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Codeforces #168 Div1 & Div2】Solutions
阅读量:7190 次
发布时间:2019-06-29

本文共 6231 字,大约阅读时间需要 20 分钟。

  转载请注明出处:

  上一次失误掉进Div2,这次也很可惜,B题读错了题又差一点。。。

【A.Lights Out】

  

  题目大意:按开关会导致周围相邻开关状态一起变化,给出操作问结果。

  简单模拟

View Code
1 #include 
2 using namespace std; 3 4 const int dx[5]={
0,1,0,-1,0}; 5 const int dy[5]={
1,0,-1,0,0}; 6 int res[5][5],x; 7 8 int main(){ 9 for(int i=1;i<=3;i++)10 for(int j=1;j<=3;j++){11 cin>>x;12 for(int k=0;k<5;k++)13 res[i+dx[k]][j+dy[k]]+=x;14 }15 for(int i=1;i<=3;i++){16 for(int j=1;j<=3;j++)17 cout<<(res[i][j]+1)%2;18 cout<

 

【B.Convex Shape】

  

  题目大意:判断所给图形是不是所谓"Convex Shape"(即任意两个格子互达且只需转向一次)

  枚举两个格子,沿着路径走就可以了= =竟然读错题了啊囧

View Code
1 #include 
2 using namespace std; 3 4 int n,m,x[3000],y[3000],cnt; 5 char s[50][50]; 6 7 bool check(int x,int a1,int b1,int y,int a2,int b2){ 8 for(int i=min(a1,b1);i<=max(a1,b1);i++) 9 if(s[x][i]!='B') return 0;10 for(int i=min(a2,b2);i<=max(a2,b2);i++)11 if(s[i][y]!='B') return 0;12 return 1;13 }14 15 int main(){16 cin>>n>>m;17 for(int i=0;i
>s[i];19 for(int j=0;j

 

【C.k-Multiple Free Set】(A in Div1)

  

  

  题目大意:从所给数集中找出最大子集,使得子集中不存在x,y,使得y=x*k。求最大子集的大小。

  我思路大体是这样的。。。

  首先我把题目抽象成一个图的问题,对于集合中x,x*k,将他们连边,最后图中会形成若干条链,不同的链一定互不干扰,问题转换成在每条链中选取尽量多的点。

  到这里就可以做了(博主就是这样做的结果时间内存都巨大),但是可以继续想

  选取尽量多的点的一种方法就是:链头上的点先选,然后隔一个点选一个。这样就有了一种贪心的方法,先将集合中数字排序,然后如果该数可选,就选,不可选就不选。

  代码1:贪心方法

View Code
1 #include 
2 #include
3 #include
4 using namespace std; 5 6 map
m; 7 int n,ans; 8 long long k,a[100010]; 9 10 int main(){11 cin>>n>>k;12 for(int i=0;i
>a[i];14 sort(a,a+n);15 for(int i=0;i

  代码2:图方法

View Code
1 #include 
2 #include
3 #include
4 #include
5 #define mn 100010 6 #define mm 200020 7 using namespace std; 8 typedef long long ll; 9 10 map
m;11 int cnt[100010],n,ans,tot;12 long long k,a[100010];13 bool vis[100010];14 15 struct EDGE{16 int pnt;17 EDGE *pre;18 EDGE(){}19 EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}20 }Edge[mm],*SP=Edge,*edge[mn];21 22 inline void addedge(int a,int b){23 edge[a]=new(++SP)EDGE(b,edge[a]);24 edge[b]=new(++SP)EDGE(a,edge[b]);25 }26 27 int dfs(int x){28 vis[x]=true;29 for(EDGE *j=edge[x];j;j=j->pre)30 if(!vis[j->pnt]){31 cnt[x]+=dfs(j->pnt) ;32 }33 return cnt[x];34 } 35 36 int main(){37 cin>>n>>k;38 for(int i=1;i<=n;i++){39 scanf("%d",&a[i]);40 cnt[i]=1;41 }42 sort(a+1,a+1+n);43 for(int i=1;i<=n;i++)44 if(!m[a[i]]) m[a[i]]=++tot;45 n=tot;46 for(int i=1;i<=n;i++){47 int tmp=m[a[i]*k];48 if(tmp>0) addedge(m[a[i]],tmp);49 }50 for(int i=1;i<=n;i++)51 if(!vis[i]){52 dfs(i);53 ans+=(cnt[i]+1)/2;54 }55 cout<
<

 

【D.Zero Tree】(B in Div1)

  

  

  题目大意,给定一棵带权树,每次可以选取包括节点1的一棵子树,使其所有点权±1,问最少操作次数使得所有节点点权为0.

  显然应该先把叶子节点变成0,然后依次向上做。dfs即可

View Code
1 #include 
2 #define mn 100010 3 #define mm 200010 4 using namespace std; 5 typedef long long ll; 6 template
inline void gmax(T &a,T b){
if(a
pre)26 if(j->pnt!=fa){27 dfs(j->pnt,x);28 gmax(t_add,add[j->pnt]);29 gmax(t_sub,sub[j->pnt]);30 }31 w[x]+=t_add-t_sub;32 if(w[x]<0) t_add-=w[x];33 else t_sub+=w[x];34 add[x]=t_add,sub[x]=t_sub;35 }36 37 int main(){38 cin>>n;39 for(int i=1;i
>a>>b;41 addedge(a,b);42 }43 for(int i=1;i<=n;i++)44 cin>>w[i];45 dfs(1,0);46 cout<
<

 

【E.】The Last Hole!(C in Div 1)

  

  

  题如其名,最后一题是个坑。。。等会写

 

【D.Lovely Matrix】(Div 1)

  

  题目大意:n×m格子,格子有权值,有空格,问是否可以交换某些列的次序,使得每一行上的数字不减。

  显然是拓扑排序。问题在于数据范围有点大,如果出现权值相同的格子,建图时逐个连边复杂度非常高。我们可以考虑附加点P[x],使权值为x的点都连向P[x],然后由P[x]连向比x大的点。

View Code
1 #include 
2 #include
3 #include
4 #define mm 200010 5 #define mn 400010 6 using namespace std; 7 8 queue
q; 9 int n,m,ans[mn],deg[mn],cnt,idx;10 struct REC{
int v,p;}a[mn];11 12 struct EDGE{13 int pnt;14 EDGE *pre;15 EDGE(){}16 EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}17 }Edge[mm],*SP=Edge,*edge[mn];18 19 inline void addedge(int a,int b){20 edge[a]=new(++SP)EDGE(b,edge[a]);21 deg[b]++;22 }23 24 inline bool cmp(REC a,REC b){
return a.v
>n>>m;28 for(int i=0;i
>a[j].v;31 a[j].p=j;32 }33 sort(a,a+m,cmp);34 for(int j=0;j
pre)48 if(!--deg[j->pnt]) q.push(j->pnt);49 }50 if(idx

【E. Mirror Room】(Div 1)

  

  题目大意:光线在镜子格里反射,问能经过多少格子。

  看了liouzhou101大神的代码明白了,其实就是用了一堆map和set然后模拟。。。。

  好不容易仿照着写出来了,但是今天CF评测机抽风,在第24个点tle,连liouzhou101的代码现在都过不了。。。

View Code
1 #include 
2 #include
3 #include
4 #include
5 #include
6 #define x first 7 #define y second 8 using namespace std; 9 typedef pair
PII;10 11 int n,m,k,ans,x,y;12 set
block,empty_cell;13 map
> vis;14 PII s,t,dir;15 char sym[5];16 17 int main(){18 cin>>n>>m>>k;19 for(int i=0;i<=n+1;i++)20 block.insert(PII(i,0)),21 block.insert(PII(i,m+1));22 for(int i=0;i<=m+1;i++)23 block.insert(PII(0,i)),24 block.insert(PII(n+1,i));25 while(k--){26 scanf("%d%d",&x,&y);27 block.insert(PII(x,y));28 }29 scanf("%d%d",&s.x,&s.y);30 scanf("%s",sym);31 dir=PII(sym[0]=='N'?-1:1,sym[1]=='W'?-1:1);32 while(true){33 if(empty_cell.insert(s).y) ans++;34 t=PII(s.x+dir.x,s.y+dir.y);35 if(!block.count(t)){36 s=t;37 continue;38 }39 if(!vis[t].insert(dir).y) break;40 x=block.count(PII(t.x-dir.x,t.y)),y=block.count(PII(t.x,t.y-dir.y));41 if (x==y) dir.x=-dir.x,dir.y=-dir.y;42 else if(x) s.x+=dir.x,dir.y=-dir.y;43 else s.y+=dir.y,dir.x=-dir.x;44 }45 cout<
<

 

  

转载于:https://www.cnblogs.com/Delostik/archive/2013/02/21/2920087.html

你可能感兴趣的文章
String、StringBuilder、StringBuffer 区别
查看>>
Linux的命令(待更新)
查看>>
plsql远程连接oracle的纠结。。
查看>>
aspx 提交按钮只能点一次
查看>>
Oracle 官方文档 结构说明(教你如何快速从官方文档中获取需要的知识)
查看>>
jQuery
查看>>
url加密 比较
查看>>
前端资源汇总[转载]
查看>>
mysql 增删改查最基本用法小结
查看>>
图和图算法
查看>>
网络流学习(转载自ssw 的博客)
查看>>
C# 测试程序运行时间
查看>>
0505.Net 基础班第十七天(GDI绘图)
查看>>
5、SuperSocket 基本配置
查看>>
4个方面教你怎么样成为一名及格的设计师
查看>>
中文分词工具thulac4j发布
查看>>
【UNIX高级编程】关于UNIX编程环境的配置(apue.h和error.h)
查看>>
第三章 熟悉常用的HDFS操作
查看>>
Google Protocol Buffer在vs2010下配置
查看>>
软件工程学习总结
查看>>