[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也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡 ...
随机推荐
- MySQL 中NULL和空值的区别,索引列可以有空值或者null吗?
空值跟null的区别.mysql官方: “NULL columns require additional space in the row to record whether their values ...
- 数据操作语句(DML)
增加(插入)数据 SQL>insert into 表名 values(值1,值2 /*根据表中的字段顺序和字段类型相应填写*/); SQL>commit; (提交,提交了别的人才看看到这个 ...
- 【Mybatis】XML配置实现增删改查
①创建数据库和表,数据库为mytest,表为users CREATE DATABASE mytest; USE mytest; DROP TABLE IF EXISTS users; CREATE T ...
- python-装饰器模式
源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 有时为了给某个对象而不是给整个类添加一个功能,使用继承机制是添加功能的一个有效途 ...
- vue 数据请求
作者QQ:1095737364 QQ群:123300273 欢迎加入! 要引入模块: vue-resource 1.在package.json中的dependencies中添加vue ...
- 自定义多选框(checkbox)和单选框(radio)css样式
直接上代码: input[type="radio"],input[type="checkbox"]{ -webkit-appearance: none; out ...
- 解决The type 'ASP.global_asax' exists in both ASP.global_asax同时存在问题
习惯发布站点的同学有时候可能遇见以下错误 这是发布时[预编译勾选/不勾选]产生的文件冲突导致的 如果不勾选预编译会发布以下代码 如果勾选预编译会发布以下代码 错误就在于此,如果非预编译Global.a ...
- Nginx的日志剖析
1.访问日志(access.log) Nginx的访问日志就是一个文件,它存储着每个用户对网站的访问请求,这个功能是有ngx_http_log_module模块来负责的,这个文件存在的主要目的就是为了 ...
- ubuntu更新下载源问题
Q1:ubuntu14.04系统安装完之后无法跟新并安装插件 cd /var/lib/apt/lists sudo rm * -rf sudo apt-get clean;sudo apt-get u ...
- HBuilder开发iPad程序不能全屏显示的解决方法
HBuilder开发iPad程序不能全屏显示的解决方法: targets选择HBuilder=>Deployment Info=> devices选择Universal即可