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.......,最 ...
随机推荐
- java分析源码-ReentrantLock
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
- poj 2724 Purifying Machinef
poj 2724 Purifying Machinef 题意 每一个01串中最多含有一个'*','*'既可表示0也可表示1,给出一些等长的这样的01串,问最少能用多少个这样的串表示出这些串.如:000 ...
- wpf 获取datagrid中模板中控件
//获取name为datagrid中第三列第一行模板的控件 FrameworkElement item = dataGrid.Columns[].GetCellContent(dataGrid.Ite ...
- asp.net Literal
常用于动态向页面添加内容 Panel panel = new Panel(); Literal literal = new Literal(); literal.Text = "<br ...
- VTK初学一,动画加AVI录制终于做出来了
#ifndef INITIAL_OPENGL #define INITIAL_OPENGL #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRe ...
- UIScrollView的常见属性
@property(nonatomic) CGPoint contentOffset; 这个属性用来表示UIScrollView滚动的位置 (其实就是内容左上角与scrollView左上角的间距值) ...
- I() 方法
I()方法的介绍及使用: http://www.jb51.net/article/51213.htm
- 如何快速上手使用STM32库函数
一.背景 如前文所述,利用标准库函数的好处在于,可以快速开发,不用去对着数据手册,小心翼翼的一位一位的配置那些繁复的寄存器,因为这些工作意法半导体已经找了一些顶级的工程师帮你做了,杰作既是其库函数.当 ...
- 【bzoj1426】收集邮票
题目描述 有n种不同的邮票,皮皮想收集所有种类的邮票.唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n.但是由于凡凡也很喜欢邮票,所 ...
- 【总结2】PhpStorm利用XDebug调试PHP技巧
在写完 [总结1]PhpStorm配置XDebug(远程)调试PHP 后,发现PhpStorm调试PHP还有一个技巧,如下图所示: 路径:File -> Settings -> Langu ...