[POI2007]MEG-Megalopolis
传送门:嘟嘟嘟
第一反应是树链剖分,但是太长懒得写,然后就想出了一个很不错的做法。
想一下,如果我们改一条边,那么影响的只有他的子树,只要先搞一个dfs序,为什么搞出这个呢?因为有一个性质:一个节点的子树在dfs序上是连续的,所以这道题就变成了一个单点查询,区间修改的线段树(树状数组)板子题。
然后我不到40分钟写完了,非说有的点TLE,debug了一个多点……现在想想,一般遇到这种情况,一定不是什么正经问题。然而当时的我并不这么想,以为线段树太慢了,改成差分+树状数组,各种优化,虽然在luogu卡了过去,然而内网却GG。
终于放弃,到网上找标程,发现写的几乎一模一样,就一行行比对……然后发现我为了省事儿读字母用了cin,按标称改成了scanf……结果最慢的点直接从900多ms变成了200多ms……然后内网秒过了……老子在此立flag:我,mrclr,如果再用cin,我就女装!
心路历程讲完了,发下代码吧
先是线段树的
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdlib>
#include<cctype>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 3e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n;
vector<int> v[maxn]; int dis[maxn], dfsx[maxn], size[maxn], pos[maxn], cnt = ;
void dfs(const int& now)
{
dfsx[now] = ++cnt; pos[cnt] = now;
size[now] = ;
for(int i = ; i < (int)v[now].size(); ++i)
{
dis[v[now][i]] = dis[now] + ;
dfs(v[now][i]);
size[now] += size[v[now][i]];
}
return;
} int l[maxn << ], r[maxn << ], dis2[maxn << ], lazy[maxn << ];
void build(const int& L, const int& R, const int& now)
{
l[now] = L; r[now] = R;
if(L == R) {dis2[now] = dis[pos[L]]; return;}
int mid = (L + R) >> ;
build(L, mid, now << );
build(mid + , R, now << | );
dis2[now] = dis2[now << ] + dis2[now << | ];
}
void pushdown(const int& now)
{
if(lazy[now])
{
lazy[now << ] += lazy[now];
lazy[now << | ] += lazy[now];
dis2[now << ] -= lazy[now];
dis2[now << | ] -= lazy[now];
lazy[now] = ;
}
}
void update(const int& L, const int& R, const int& now)
{
if(!dis2[now]) return;
if(l[now] == L && r[now] == R)
{
dis2[now]--; lazy[now]++;
return;
}
pushdown(now);
int mid = (l[now] + r[now]) >> ;
if(R <= mid) update(L, R, now << );
else if(L > mid) update(L, R, now << | );
else {update(L, mid, now << ); update(mid + , R, now << | );}
}
int query(const int& id, const int& now)
{
if(!dis2[now]) return ;
if(l[now] == r[now]) return dis2[now];
pushdown(now);
int mid = (l[now] + r[now]) >> ;
if(id <= mid) return query(id, now << );
else return query(id, now << | );
} int main()
{
n = read();
for(int i = ; i < n; ++i)
{
int x = read(), y = read();
if(y < x) swap(x, y);
v[x].push_back(y);
}
dfs();
build(, cnt, );
int m = read();
char ch[];
for(int i = ; i < n + m; ++i)
{
scanf("%s", ch);
if(ch[] == 'W')
{
int x = read();
write(query(dfsx[x], )); enter;
}
else
{
int x = read(), y = read();
if(y > x) swap(x, y);
update(dfsx[x], dfsx[x] + size[x] - , );
}
}
return ;
}
然后又写了个差分+树状数组
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdlib>
#include<cctype>
using namespace std;
#define enter printf("\n")
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 3e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n;
vector<int> v[maxn]; int dis[maxn], dfsx[maxn], size[maxn], pos[maxn], cnt = ;
void dfs(const int& now)
{
dfsx[now] = ++cnt; pos[cnt] = now;
size[now] = ;
if(!v[now].size()) return;
for(int i = ; i < (int)v[now].size(); ++i)
{
dis[v[now][i]] = dis[now] + ;
dfs(v[now][i]);
size[now] += size[v[now][i]];
}
} int cf[maxn], c[maxn];
inline int lowbit(int x)
{
return x & -x;
}
void add(int pos, int x)
{
while(pos <= cnt)
{
c[pos] += x;
pos += lowbit(pos);
}
}
int sum(int pos)
{
int ret = ;
while(pos)
{
ret += c[pos];
pos -= lowbit(pos);
}
return ret;
} int main()
{
n = read();
for(int i = ; i < n; ++i)
{
int x = read(), y = read();
if(y < x) swap(x, y);
v[x].push_back(y);
}
dfs();
for(int i = ; i <= cnt; ++i) cf[i] = dis[pos[i]] - dis[pos[i - ]];
for(int i = ; i <= cnt; ++i) add(i, cf[i]);
int m = read();
char ch[];
for(int i = ; i < n + m; ++i)
{
scanf("%s", ch);
if(ch[] == 'W')
{
int x = read();
write(sum(dfsx[x])); enter;
}
else
{
int x = read(), y = read();
if(y > x) swap(x, y);
add(dfsx[x], -); add(dfsx[x] + size[x], );
}
}
return ;
}
虽然都能过,不过树状数组比线段树快了一倍
[POI2007]MEG-Megalopolis的更多相关文章
- NOIp2018 复习笔记
其实也没什么用啦,只是来占个坑 OI知识 3367 [模板]并查集 就这么做啊 没什么其他的 就是可以做tarjan LCA和Kruskal的操作 //关键函数 int getfa(int t) { ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- BZOJ 1103: [POI2007]大都市meg
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2189 Solved: 1160[Submit][Sta ...
- [bzoj1103][POI2007]大都市meg(树状数组+dfs序)
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2031 Solved: 1069[Submit][Sta ...
- 【BZOJ】【1103】【POI2007】大都市meg
dfs序 模板题,进点+1出点-1,刚好对于不在路径上的点一进一出刚好抵消,由于本题要动态修改(变成公路以后+1-1都变成0)所以在序列上套一个树状数组即可. TLE:1.递归dfs给爆了……写了个手 ...
- 数据结构(线段树):BZOJ 1103 [POI2007]大都市meg
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1791 Solved: 925[Submit][Stat ...
- BZOJ 1103: [POI2007]大都市meg( 树链剖分 )
早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了.. 树链剖分 , 为什么跑得这么慢... ------------------------------------------- ...
- bzoj1103【POI2007】大都市meg
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1544 Solved: 776 [Submit][St ...
- BZOJ1103 [POI2007]大都市meg 【树剖】
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3038 Solved: 1593 [Submit][S ...
- 树状数组【bzoj1103】: [POI2007]大都市meg
1103: [POI2007]大都市meg 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡 ...
随机推荐
- ExtJs 中Viewport的介绍与使用
ExtJs 中Viewport的介绍与使用 VeiwPort 代表整个浏览器显示区域,该对象渲染到页面的body 区域,并会随着浏览器显示区域的大小自动改变,一个页面中只能有一个ViewPort 实例 ...
- [日常] Go语言圣经--示例: 并发的Clock服务习题
练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结 ...
- Python发送短信提醒
Python发送短信可借助腾讯云平台提供的短信服务 发送短信需要的及格参数: 1.SDK_AppID和SDK_Key 2.签名: 3.模板ID 下面贴出源码DEMO: from qcloudsms_p ...
- 开放本地MYSQL服务器端口
有时候别人需要连接你的数据库,这个时候你就要开放数据库的端口,让别的主机可以连接上,步骤如下: 1.打开防火墙,新建入站规则,开放MySQL3306端口 2.执行以下两个命令: (1)如果你想允许用户 ...
- ETCD 简介 + 使用
etcd简介 etcd是一个高可用的分布式键值(key-value)数据库.etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现. etcd是一个服务发现系统,具备以下的特点: 简单: ...
- Windows系统的消息机制
1)Add the window to the clipboard viewer chain. 通过SetClipboardViewer()传入窗口句柄,所有监视剪贴板的窗口句柄会组成一个链表(后来者 ...
- php扩展php-redis安装与使用
一.redis的安装 1,安装redis版本 下载页面:https://redis.io/download 安装一个老版本3.2.11:http://download.redis.io/release ...
- 启动HDFS时datanode无法启动的坑
启动HDFS 启动hdfs,进入sbin目录,也可以执行./start-all.sh - $cd /app/hadoop/hadoop-2.2.0/sbin - $./start-dfs.sh 在此之 ...
- PHP定界符<<<eof 使用
PHP是一个Web编程语言,在编程过程中难免会遇到用echo来输出大段的html和javascript脚本的情况,如果用传统的输出方法 ——按字符串输出的话,肯定要有大量的转义符来对字符串中的引号等特 ...
- Software-Defined Networking A Comprehensive Survey --阅读_day2
3. 什么是SDN?(WHAT IS SOFTWARE-DEFINED NETWORKING?) The term SDN was originally coined to represent the ...