2015年ACM长春网络赛(准备做掉7道:已经更新到6道)
总结汇总:模板
int getmax_min(char s[]) {//字符串的最大表示法:返回最小数组下标 , j = , k = ; while(i < len && j < len) { k = ; while(s[i+k] == s[j+k] && k < len) k++; if(k == len) return min(i,j); if (s[i + k] < s[j + k]) > j) i = i + k + ; else i = j + ; > i) j = j + k + ; else j = i + ; } return min(i, j); }
A题。水题。优先队列。纯模拟。
WA了很久很久的经验教训就是 好好审题 好好写题 把数据范围套串了 简直了
有几个要 注意的wa点
1.不同数据各自的数据范围别看错了
2.审题,最后的最后,是要把所有的朋友都放进来的
3.若两个人同时满足进入条件的时候,价值高的先进,价值相同的,先来的先进。
4.还有还有!!!!队列啊栈啊这种数据结构一定要注意 判空!判空!!!
#include <cstdio> #include <queue> #include <algorithm> using namespace std; + ; int ans[maxn]; struct ss { int val,id; ]; bool operator < (const ss& other)const { if(val != other.val) return val < other.val; return id > other.id; } }stu[maxn]; struct sss { int t,p; bool operator < (const sss& other)const { return t < other.t; } }door[maxn]; int main() { int T,k,m,q; scanf("%d",&T); while(T--) { priority_queue<ss>que; scanf("%d%d%d",&k,&m,&q); ; i <= k; i++) { scanf("%s %d", stu[i].name, &stu[i].val); stu[i].id = i; } ; i < m; i++) { scanf("%d%d", &door[i].t, &door[i].p); } sort(door, door + m); , outid = ; ; i < m; i++) { while(stu[cnt].id <= door[i].t && cnt <=k) { que.push(stu[cnt]); cnt++; } while((door[i].p--) && (!que.empty())) { ss temp = que.top(); que.pop(); ans[ outid ] = temp.id; outid ++; } } while(cnt <= k) que.push(stu[cnt++]); while(!que.empty()) { ss temp = que.top(); que.pop();ans[ outid ] = temp.id; outid ++; } int x; ; i < q; i++) { scanf("%d",&x); printf()?'\n':' '); } } ; }
题目大意应该是不断的把 连接的池塘少于两个的 池塘移除。最后各个连通分量中,拥有奇数个池塘的价值总和。
怎么解决这个问题呢。相当于移除所有度数小于2的顶点。是用一个类似于。拓扑排序的思路。
d数组:用来记录顶点的度数。vis数组:来标记是否应该被移除。
void toposort() { queue<int>que; ;i<=n;i++) ) { vis[i] = ; que.push(i); } while(!que.empty()) { int t = que.front();que.pop(); ;i<G[t].size();i++) { int v = G[t][i]; ) { d[v]--; ) { vis[v] = ; que.push(v); } } } } }
那如何统计。各个连通分量中的顶点个数呢,用dfs。搜索。
另外就是注意!sum的类型应该是LL的。高亮部分叠加的时候,要注意val数组是int型的。
#include <cstdio> #include <queue> #include <vector> #include <cstring> using namespace std; typedef long long LL; + ; int n,m,T,x,y,d[maxn],vis[maxn],val[maxn]; LL sum,amount; vector<int>G[maxn]; void toposort() { queue<int>que; ;i<=n;i++) ) { vis[i] = ; que.push(i); } while(!que.empty()) { int t = que.front();que.pop(); ;i<G[t].size();i++) { int v = G[t][i]; ) { d[v]--; ) { vis[v] = ; que.push(v); } } } } } void dfs(int s) { vis[s] = ; ;i<G[s].size();i++) { int v = G[s][i]; ) { amount++; sum = sum + (LL)val[v]; dfs(v); } } } int main() { scanf("%d",&T); while(T--) { memset(d,,sizeof(d)); memset(vis,,sizeof(vis)); ;i<=maxn;i++) G[i].clear(); scanf("%d%d",&n,&m); ;i<=n;i++) scanf("%d",&val[i]); ;i<m;i++) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); d[x]++, d[y]++; } toposort(); LL tot = ; ;i<=n;i++) { ) {//说明未被删除 sum = val[i]; amount = ; dfs(i); == ) tot = tot + sum; } } printf("%lld\n",tot); } }
注意一下题意就好了,它不是让你求最短路,是每段小于那个给出的值就可以了。
在这张图上,权值小于等于给定值的路,相关的顶点有一个c(n,2)的组合。也就是n*(n-1)/2
在并查集里加一个数组记录一下这个并查集里面的结点的总数就行了。
哦对了,这里最关键的是,利用离线处理,而不是在线处理来提高效率。
#include <cstdio> #include <map> #include <set> #include <queue> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) + ; struct QQ { int w,id; bool operator <(const QQ& other) { return w < other.w; } }Q[+]; + ]; struct edge { int x,y,w; bool operator <(const edge& other) { return w < other.w; } }es[ + ]; int pa[maxn], num[maxn]; void init(int n) { ;i<=n;i++) pa[i] = i, num[i] = ; } int uf_find(int x){return x == pa[x] ? x : (pa[x] = uf_find(pa[x]));} void join(int x,int y) { int fx = uf_find(x);int fy = uf_find(y); if(fx != fy) pa[fx] = fy, num[fy] += num[fx]; } int main() { int T,n,m,q; scanf("%d",&T); while(T--) { scanf("%d%d%d", &n, &m, &q); init(n); ;i<m;i++) { scanf("%d%d%d", &es[i].x, &es[i].y, &es[i].w); } sort(es, es + m); ;i<q;i++) { scanf("%d",&Q[i].w); Q[i].id = i; } sort(Q, Q + q); , j = ; ;i<q;i++) { while(j < m && es[j].w <= Q[i].w) { int fx = uf_find(es[j].x); int fy = uf_find(es[j].y); j++; if(fx == fy) continue; cnt += (num[fx] + num[fy]) * (num[fx] + num[fy] - ) -num[fx] * (num[fx] - ) -num[fy] * (num[fy] - ); join(fx,fy); } ans[ Q[i].id ] = cnt; } ; i < q; i++) { printf("%d\n",ans[i]); } } ; }
这道题。字符串的最大表示法。
getmax_min函数是最大表示中取最小的数组下标,_max就是取最大的数组下标。
要有一步,预处理:
; i < len; i++) { ss[*len-i-] = ss[len-i-] = s[i+len] = s[i]; } ss[*len] = *len] = '\0';//容易遗漏
然后把,表示出来的两个字符串放到两个新的数组中保存。
; i < len; i++) { s_0[i] = s[ans_0+i]; s_1[i] = ss[ans_1+i]; } s_0[len] = s_1[len] = '\0';
接下来就是根据题意进行一些列判定和输出就行了。
主干代码在两个函数上。
需要注意的地方,都有高亮了。
第二个函数中k == len之后的处理,很关键,是哪来找循环节的,不然算法会退化到n²。
其他的怎么理解,昂,只能自己画图吧,画着画着就懂了吧。。。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; + ; *maxn], ss[*maxn], s_0[maxn], s_1[maxn]; int T,len; int getmax_min(char s[]) { , j = , k = ; while(i < len && j < len) { k = ; while(s[i+k] == s[j+k] && k < len) k++; if(k == len) return min(i,j); if (s[i + k] < s[j + k]) > j) i = i + k + ; else i = j + ; > i) j = j + k + ; else j = i + ; } return min(i, j); } int getmax_max(char s[]) { , j = , k= ; while(i < len && j < len) { k = ; while(s[i + k] == s[j + k] && k < len) k++; if (k == len) { int loop = abs(i - j); return len - loop + i; } else { if (s[i + k] < s[j + k]) > j) i = i + k + ; else i = j + ; > i) j = j + k + ; else j = i + ; } } if(j >= len) return i; return j; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&len); scanf("%s",s); ; i < len; i++) { ss[*len-i-] = ss[len-i-] = s[i+len] = s[i]; } ss[*len] = *len] = '\0'; int ans_0 = getmax_min(s); int ans_1 = getmax_max(ss); ; i < len; i++) { s_0[i] = s[ans_0+i]; s_1[i] = ss[ans_1+i]; } s_0[len] = s_1[len] = '\0'; int p = strcmp(s_0, s_1); ) { printf(); } ) { printf("%d 1\n", len - ans_1); } else { < len - ans_1) { printf(); } else { printf("%d 1\n", len - ans_1); } } } ; }
裸的线段树(建树+区间和查询)。。。。没啥说的,模板题。
#include <cstdio> #include <map> #include <set> #include <queue> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; #define mem0(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define lson l, m, rt << 1 #define rson m+1, r, rt << 1 | 1 ; ]; ], MAX[rt << | ]);} void build(int l,int r,int rt) { if(l == r) {scanf("%d",&MAX[rt]);return ;} ; build(lson), build(rson); pushup(rt); } int query(int ll,int rr,int l,int r,int rt) { if(ll <= l && rr >= r) return MAX[rt]; ; ; if(ll <= m ) ans = max(ans, query(ll,rr,lson)); if(rr > m) ans = max(ans, query(ll,rr,rson)); return ans; } int main() { int t, x, y, m, n; scanf("%d",&t); while(t--) { scanf("%d",&n); build(,n,); scanf("%d",&m); ;i<m;i++) { scanf("%d%d",&x,&y); ,n,); printf("%d\n",ans); } } ; }
!!!其实就是个,给树的中序遍历和前序遍历的结果,构造个树。。然后dfs一下就好了。如果看出来是 中序+前序 这题就变得非常水了。
#include <cstdio> ],]; struct A { int left,right; }node[]; int build(int l1,int r1,int l2,int r2) { ; int root = pre[l2]; int p = l1; while(in[p] != root) p++; int cnt = p - l1; node[root].left = build(l1, l1+cnt-,l2+,l2+cnt); node[root].right = build(l1+cnt+,r1,l2+cnt+,r2); return root; } void dfs(int x,int root) { ) { printf("E"),dfs(x,node[root].left); } ) printf("W"),dfs(x,node[root].right); else return ; } int main() { int T,n,m; scanf("%d", &T); while(T--) { scanf("%d",&n); ; i <= n; i++) scanf("%d",&pre[i]),in[i] = i; ,n,,n); scanf("%d",&m); ; i < m; i++) { int x; scanf("%d",&x); dfs(x,root); puts(""); } } ; }
2015年ACM长春网络赛(准备做掉7道:已经更新到6道)的更多相关文章
- 2015年ACM长春区域赛比赛感悟
距离长春区域赛结束已经4天了,是时候整理一下这次比赛的点点滴滴了. 也是在比赛前一周才得到通知要我参加长春区域赛,当时也是既兴奋又感到有很大的压力,毕竟我的第一场比赛就是区域赛水平,还是很有挑战性的. ...
- 2015年ACM沈阳网络赛(准备做掉4道:)
Traversal Best Solver Minimum Cut Dividing This Product Excited Database Fang Fang Matches Puzzle Ga ...
- HDU 4763 Theme Section (2013长春网络赛1005,KMP)
Theme Section Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- HDU 4764 Stone (2013长春网络赛,水博弈)
Stone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- HDU 4762 Cut the Cake (2013长春网络赛1004题,公式题)
Cut the Cake Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- HDU 4759 Poker Shuffle(2013长春网络赛1001题)
Poker Shuffle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- HDU 4768 Flyer (2013长春网络赛1010题,二分)
Flyer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 2012年长春网络赛(hdu命题)
为迎接9月14号hdu命题的长春网络赛 ACM弱校的弱菜,苦逼的在机房(感谢有你)呻吟几声: 1.对于本次网络赛,本校一共6名正式队员,训练靠的是完全的自主学习意识 2.对于网络赛的群殴模式,想竞争现 ...
- Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)
题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最 ...
随机推荐
- 创建一个自定义颜色IRgbColor
后续文章需要用到,很简单的一个小函数 /// <summary> /// 自定义颜色 /// </summary> /// <param name="r&quo ...
- ecshop 支付
支付分成两部分 1.订单信息 2.支付日志ID 3.生成支付代码 一次性支付完成 // 支付信息 include_once('includes/lib_payment.php'); $order['l ...
- 在Application中集成Microsoft Translator服务之获取访问令牌
我在这里画了一张图来展示业务逻辑 在我们调用microsoft translator server之前需要获得令牌,而且这个令牌的有效期为10分钟.下表列出所需的参数和对于的说明 参数 描述 clie ...
- JQuery常用代码汇总
获取<input />的value $("#id").val( ); 标签间的html $("#id").html('<tr><t ...
- UI第九节——UIStepper
- (void)viewDidLoad { [super viewDidLoad]; // 实例化UIStepper,大小是固定的 UIStepper *stepper = ...
- 【C语言入门教程】目录/大纲
第一章 C语言编程基础 1.1 基本程序结构 1.2 函数库 和 链接 1.3 C语言“32个”关键字 第二章 数据类型.运算符和表达式 2.1 数据类型(5种基本数据类型),聚合类型与修饰符 2.2 ...
- MySQL replace into 使用详解 及 注意事项
REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.注意:除非表 ...
- python set
set是一个工厂函数(filter也是工厂函数),是一个可变的集合 frozenset 不可变的集合,与set共性,他也在内部自动去重, >>> num5=frozenset([1, ...
- Eclipse 的单步调试
1.设置断点在程序里面放置一个断点,也就是双击需要放置断点的程序左边的栏目上. 2.调试(1)点击"打开透视图"按钮,选择调试透视图,则打开调试透视图界面,然后先设置断点,按调试按 ...
- cf595d
题意:给出一个轮子,上面有一个随着它转动的传感器在圆周上,给出一个指定距离m,和轮子向前行进的速度v以及轮子的半径r.问让传感器通过该距离最少需要多少时间. 分析:首先我们列出传感器行进距离与时间的轮 ...