[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也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡 ...
随机推荐
- eclipse连接VisualSVN Server
1.下载安装VisualSVN Server 2.修改资源库的网络连接.去掉默认的选中,修改端口,点击ok. 3.新建资源库Test,显示连接的地址http://svnybb/svn/Test/ .之 ...
- MyBatis动态添加—trim标签
做添加时,部分字段有值,没值的字段不添加,这就是动态添加,使用 trim 标签就可以实现. <insert id="insertSysUser" parameterType= ...
- 如何调试JDK源代码并查看局部变量值
如下图: 按F5进入String.startsWith,如下: 点“Edit Source Lookup Path” 附加源代码,如下图: 附加上源代码后如下: 可以看到,当鼠标放在“prefix”上 ...
- Java JDBC MySQL
一.驱动 下载地址:https://dev.mysql.com/downloads/connector/j/ 二.数据库连接配置 jdbc:mysql://address:port/database? ...
- java.lang.ExceptionInInitializerError异常
今天在开发的过程中,遇到java.lang.ExceptionInInitializerError异常,百度查了一下,顺便学习学习,做个笔记 静态初始化程序中发生意外异常的信号,抛出Exception ...
- CentOS 7环境下Pycharm安装流程记录
1.准备安装文件: 方法1: 使用内置火狐浏览器访问下载最新格式为tar.gz的压缩包 网址:https://www.jetbrains.com/pycharm/download/previous.h ...
- webpack打包小图片时进行Base64转码
关于base64 优点: base64就是一串字符串码表示的图片,在加载页面和js时一块加载出来,减少了加载图片时的http请求.加载一张图片时会发起一次http请求,http请求每次建立都会需要一定 ...
- BZOJ2388: 旅行规划(分块 凸包)
题意 题目链接 Sol 直接挂队爷的题解了 分块题好难调啊qwq #include<bits/stdc++.h> #define LL long long using namespace ...
- AndroidGradle最实用的指南
AndroidStudio目前已经成为Android开发人员的主流工具,而Gradle的原理,配置,使用仍然是很多android开发人员感到困惑的地方.网上虽然有很多相关文档,但是要么是只会用但是不知 ...
- CSS 小结笔记之BFC
BFC 即为Block formatting context 的缩写,BFC 主要用来将一个盒子设置为一个隔离的容器,不管盒子内部的元素具有什么属性,都不会影响到盒子的外面. 1.哪些元素能产生BFC ...