设为首页 加入收藏

TOP

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历(二)
2017-10-12 18:16:01 】 浏览:4336
Tags:2017ZZUACM 选拔 试题 部分 题解 ---- 纪念 卡线滚 美好 经历
0
} 21 int searchit(int len)//查找 22 { 23 int addr=lg2(len);//选择入口 24 set<int>::iterator itit; 25 for(itit=kxcs[addr].begin();itit!=kxcs[addr].end();itit++)//从入口开始遍历 26 { 27 int getcs=*itit; 28 if(kx[getcs]>=len) 29 { 30 int afterlen=kx[getcs]-len; 31 int aftercs=getcs+len; 32 kx[aftercs]=afterlen; 33 deleteit(getcs); 34 if(afterlen!=0) 35 { 36 insertit(aftercs,afterlen); 37 } 38 return getcs; 39 } 40 } 41 return 0; 42 } 43 void insertit(int insertcs,int len)//添加 起始地址与长度 44 { 45 int addr=lg2(len); 46 mem.insert(insertcs);//更新总数据 47 kx[insertcs]=len; 48 for(int i=0;i<=addr;i++)//更新分组数据 49 { 50 kxcs[i].insert(insertcs); 51 } 52 /* for(set<int>::iterator itit=mem.begin();itit!=mem.end();itit++) 53 { 54 cout<<*itit<<endl; 55 }*/ 56 } 57 void deleteit(int deletecs) 58 { 59 int addr=lg2(kx[deletecs]); 60 kx[deletecs]=0; 61 mem.erase(deletecs); 62 for(int i=0;i<=addr;i++) 63 { 64 kxcs[i].erase(deletecs); 65 } 66 } 67 int m,n,sta,di,mi; 68 int main() 69 { 70 memset(kx,0,sizeof(kx)); 71 kx[maxn]=maxn; 72 scanf("%d %d",&n,&m); 73 mem.insert(0); 74 mem.insert(maxn);//用于保护,以免出现段错误 75 insertit(1,n); 76 while(m--) 77 { 78 scanf("%d",&sta); 79 if(sta==1) 80 { 81 scanf("%d",&mi); 82 printf("%d\n",searchit(mi)); 83 } 84 else 85 { 86 scanf("%d %d",&di,&mi); 87 int flag=false; 88 int si=di; 89 if(si>n)continue; 90 int ei=di+mi-1; 91 if(ei>n)ei=n;//限制边界 92 pr=mem.equal_range(di);//该函数可以从容器中返回第一个大于等于或大于指定数的数 93 it=pr.first; 94 it--;//往后一个即为最后一个比它小的 95 if(*it+kx[*it]-1>=ei&&*it+kx[*it]-1>=si-1)continue;//新区间直接被原先区间覆盖,那该次释放无意义 96 if(*it+kx[*it]-1>=si-1)//如果最后一个比它小的结束地址大于本次释放区间起始地址,则这两个区间将连起来,初始地址将是*it 97 { 98 si=*it; 99 deleteit(*(it++));//先删除该区间,下面重建,因为还不知道区间长度 100 } 101 else it++; 102 while(true) 103 { 104 if(*it+kx[*it]-1>ei)//遍历新的释放空间会重合的所有区间,当某区间结束地址比新区间的结束地址大时遍历结束 105 { 106 if(*it<=ei+1)//该区间与新区间相连接起来 107 { 108 ei=*it+kx[*it]-1; 109 deleteit(*it);//连接起来则全算为新区间的,把该区间删除 110 } 111 insertit(si,ei-si+1);//把新区间加进去 112 break; 113 } 114 if(*it<=ei) 115 { 116 deleteit(*(it++));//区间起始地址小于等于新区间结束地址都是要和新区间重合的 117 } 118 else it++; 119 } 120 } 121 } 122 return 0; 123 }

题目 C :V型积木

Time Limit: 1 Sec  Memory Limit: 128 MB
Description
 Dr.Wu的宝宝1岁了,所以Dr.Wu准备买些积木给宝宝玩,促进孩子大脑的发育。由于宝宝太小,
所以他将高低不同的积木摆放的毫无规律(如图A)。然而Dr.Wu发现,如果从当前的积木中抽走
一部分(图B,C中虚线的即表示抽走的积木),剩下的积木能够呈现出“V”形,即积木的高度先
严格递减,然后严格递增。图B中,需要抽走三个积木,剩下的积木就可以呈现出“V”形,而图C
中仅需抽走一根积木。Dr.Wu需要你帮忙找出最少抽走多少积木,剩下的积木就能呈现出“V”型? Input 第一行: T     表示以下有T组测试数据(
1≤T ≤8) 对每组测试数据: 第一行:    N表示积木的个数。 (2<N<=100), 第二行是空格隔开的N个正整数,每个正整数Hi表示第i个积木的高度(0<Hi<=10000)。 输出中,仅一个数,即最少抽走的积木数。如果怎么抽走积木都无法呈现出“V”形,则输出“No Solution”。 Output 每组测试数据,输出占一行,仅一个数,即最少抽走的积木数。如果怎么抽走积木都无法呈现出“V”形,则输出“No Solution”。 Sample Input 2 6 50 30 40 10 20 60 6 5 4 3 1 2 6 Sample Output 1 0

题解:一开始想着bfs来着,然后gg。后来学习到最长上升子序列,然后就明白了什么...遍历每一个积木,求得其左边序列的最长下降子序列以及右边最长上升子序列,和最大的就是抽掉的最少的。

如诺手机查看代码不好看请转:http://paste.ubuntu.com/24387742/

#include <bits/stdc++.h>

using namespace std;
int shumu;
int jm[1050];
int b[1050];
int wei
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇bzoj3289 -- 莫队+树状数组 下一篇C++实现的控制台-贪吃蛇

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目