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.......,最 ...
随机推荐
- 机器学习笔记—svm算法(上)
本文申明:本文原创,如转载请注明原文出处. 引言:上一篇我们讲到了logistic回归,今天我们来说一说与其很相似的svm算法,当然问题的讨论还是在线性可分的基础下讨论的. 很多人说svm是目前最好的 ...
- 图解JVM字节码执行引擎之栈帧结构
一.执行引擎 “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...
- mysql_fetch_array,mysql_fetch_row,mysql_fetch_assoc区别
array mysql_fetch_array ( result [, int result_type] ) 返回:根据从结果集取得的行生成的数组,如果没有更多行则返回 FALSE. int ...
- List拆分成多个集合
如果对一组大的集合进行操作,想分组进行,比如批量新增10000条数据,想100条分成一个集合分成100个集合,对集合进行操作100次,用C#如何编写,这里记录下代码如下 //构造被分隔的集合 List ...
- ActiveMQ启动多个broker
具体步骤如下: 1.把activemq目录下的conf文件复制一份,叫做conf2, 命令: cp -r conf conf2 2.修改conf2目录下的activemq.xml文件 a.修改brok ...
- 二叉树的层序遍历 BFS
二叉树的层序遍历,或者说是宽度优先便利,是经常考察的内容. 问题一:层序遍历二叉树并输出,直接输出结果即可,输出格式为一行. #include <iostream> #include &l ...
- 2015.4.21 实现一般免登陆,微博QQ分享,字体自适应等
1.实现一般的登录验证和免登陆: 解决方法:node方法代码,nodeJS实现的session模块,不完整,但能用,仅供参考. 语言无所谓,session的机制都是一样的,实现不一样而已,: 2. ...
- [Python] 学习资料汇总
Python是一种面向对象的解释性的计算机程序设计语言,也是一种功能强大且完善的通用型语言,已经有十多年的发展历史,成熟且稳定.Python 具有脚本语言中最丰富和强大的类库,足以支持绝大多数日常应用 ...
- Javascript的动态增加‘类’的方法
1.我们可以为每一个实例对象增加方法.也就是说我们在每次使用‘类’之外的方法时候,都需要创建一次. function Dog(){ window.alert('I am a dog!'); } va ...
- SVN版本控制与分支设置
使用SVN+Eclipse做软件版本控制. (2009年5月) 1,SVN目录结构 Trunk : 主干目录,此目录下的文件为基准文件 Branches : 用于开发的分支目录 Tags : 用于发布 ...