[Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)
这道题一上手就知道怎么做了= =
直接求出原光路和从目标点出发的光路,求这些光路的交点就行了
然后用树状数组+扫描线或函数式线段树就能过了= =
大量的离散+模拟+二分什么的特别恶心,考试的时候是想到了不过被代码难度吓到了根本不想写QAQ
这时官方的代码就显现出了c++的STL的强大功能了
离散sort+unique+resize+lower_bound直接秒杀,模拟也是lower_bound+讨论直接秒杀
不得不让我这种一直还在手打二分的情何以堪啊QAQ
比较一下吧 官方3K,一同学(c++)6K,两初中的(Pascal)9K和20K (不得不感叹初中生已经突破天际了啊= =,不过那个20K的6个快排也是醉了= =)
CODE:(强烈建议学习其离散化的写法)
#include <iostream>
#include <vector>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio> using namespace std; #define MAXN (1 << 17)
#define MAXVAL 1000000000 int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0}; map<int, vector<pair<int, char> > > objx;
map<int, vector<pair<int, char> > > objy; pair<pair<int, int>, char> getnext(int x, int y, int dir) {
bool vmove = dir % 2 == 0;
int a = vmove ? x : y;
int b = vmove ? y : x;
int db = vmove ? dy[dir] : dx[dir];
vector<pair<int, char> >& objs = (vmove ? objx : objy)[a]; int id = lower_bound(objs.begin(), objs.end(), make_pair(b, (char)0))
- objs.begin(); id += db;
char ch = '?';
if(id < 0) {
b = -(MAXVAL + 1);
} else if(id == objs.size()) {
b = MAXVAL + 1;
} else {
b = objs[id].first;
ch = objs[id].second;
}
return make_pair(vmove ? make_pair(a, b) : make_pair(b, a), ch);
} vector<pair<int, int> > getpath(int x, int y, int dir) {
pair<int, int> pos(x, y);
vector<pair<int, int> > path(1, pos);
for(;;) {
pair<pair<int, int>, char> res = getnext(pos.first, pos.second,
dir);
pos = res.first;
path.push_back(pos); if(res.second == '/') {
dir = (dir + (dir % 2 != 0 ? 3 : 1)) % 4;
} else if(res.second == '\\') {
dir = (dir + (dir % 2 == 0 ? 3 : 1)) % 4;
} else {
break;
}
}
return path;
} vector<pair<int, pair<int, int> > >
getverts(vector<pair<int, int> >& path) {
vector<pair<int, pair<int, int> > > ret;
for(int i = 0; i + 1 < path.size(); i++) {
if(path[i].first == path[i + 1].first) {
ret.push_back(make_pair(path[i].first,
make_pair(path[i].second, path[i + 1].second)));
if(ret.back().second.second < ret.back().second.first) {
swap(ret.back().second.first, ret.back().second.second);
}
}
}
return ret;
} vector<pair<int, pair<int, int> > >
gethorz(vector<pair<int, int> >& path) {
vector<pair<int, pair<int, int> > > ret;
for(int i = 0; i + 1 < path.size(); i++) {
if(path[i].second == path[i + 1].second) {
ret.push_back(make_pair(path[i].second,
make_pair(path[i].first, path[i + 1].first)));
if(ret.back().second.second < ret.back().second.first) {
swap(ret.back().second.first, ret.back().second.second);
}
}
}
return ret;
} int BT[MAXN]; /* Logically executes array[x] += v. */
void bit_add(int x, int v) {
for(int i = x | MAXN; i < (MAXN << 1); i += i & -i) {
BT[i ^ MAXN] += v;
}
} /* Returns the sum of array[i] for 0 <= i < x */
int bit_get(int x) {
int ret = 0;
for(int i = x - 1; x != 0; i &= i - 1) {
ret += BT[i];
if(!i) break;
}
return ret;
} int countints(vector<pair<int, pair<int, int> > > vs,
vector<pair<int, pair<int, int> > > hs) {
/* Start with a coordinate compression of y values. */
vector<int> ys;
for(int i = 0; i < vs.size(); i++) {
ys.push_back(vs[i].second.first);
ys.push_back(vs[i].second.second);
}
for(int i = 0; i < hs.size(); i++) {
ys.push_back(hs[i].first);
}
sort(ys.begin(), ys.end());
ys.resize(unique(ys.begin(), ys.end()) - ys.begin());
for(int i = 0; i < vs.size(); i++) {
vs[i].second.first = lower_bound(ys.begin(), ys.end(),
vs[i].second.first) - ys.begin();
vs[i].second.second = lower_bound(ys.begin(), ys.end(),
vs[i].second.second) - ys.begin();
}
for(int i = 0; i < hs.size(); i++) {
hs[i].first = lower_bound(ys.begin(), ys.end(), hs[i].first) - ys.begin();
} /* Sort vertical intervals by x, create event list. */
sort(vs.begin(), vs.end());
vector<pair<pair<int, int>, int> > events;
for(int i = 0; i < hs.size(); i++) {
events.push_back(make_pair(make_pair(hs[i].second.first, hs[i].first), 1));
events.push_back(make_pair(make_pair(hs[i].second.second,
hs[i].first), -1));
}
sort(events.begin(), events.end()); /* Finally, count the intersections using a Fenwick tree. */
int result = 0;
memset(BT, 0, sizeof(BT));
for(int i = 0, j = 0; i < events.size(); i++) {
int x = events[i].first.first;
for(; j < vs.size() && vs[j].first < x; j++) {
result += bit_get(vs[j].second.second) - bit_get(vs[j].second.first + 1);
}
bit_add(events[i].first.second, events[i].second);
}
return result;
} int main() {
freopen("optics.in", "r", stdin);
freopen("optics.out", "w", stdout); int N, bx, by;
cin >> N >> bx >> by; objx[0].push_back(make_pair(0, 'S'));
objy[0].push_back(make_pair(0, 'S'));
objx[bx].push_back(make_pair(by, 'B'));
objy[by].push_back(make_pair(bx, 'B'));
for(int i = 0; i < N; i++) {
int x, y;
string mr;
cin >> x >> y >> mr; objx[x].push_back(make_pair(y, mr[0]));
objy[y].push_back(make_pair(x, mr[0]));
}
for(map<int, vector<pair<int, char> > >::iterator it =
objx.begin();
it != objx.end(); ++it) {
sort(it->second.begin(), it->second.end());
}
for(map<int, vector<pair<int, char> > >::iterator it =
objy.begin();
it != objy.end(); ++it) {
sort(it->second.begin(), it->second.end());
} int result = 0;
vector<pair<int, int> > plaser = getpath(0, 0, 0);
for(int i = 0; i < 4; i++) {
vector<pair<int, int> > pbarn = getpath(bx, by, i); int res = countints(getverts(plaser), gethorz(pbarn)) +
countints(getverts(pbarn), gethorz(plaser));
if(pbarn[0] == pbarn.back()) {
result += res;
} else {
result += 2 * res;
}
}
cout << result / 2 << endl; return 0;
}
[Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)的更多相关文章
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- bzoj4785:[ZJOI2017]树状数组:二维线段树
分析: "如果你对树状数组比较熟悉,不难发现可怜求的是后缀和" 设数列为\(A\),那么可怜求的就是\(A_{l-1}\)到\(A_{r-1}\)的和(即\(l-1\)的后缀减\( ...
- HDU - 1166 树状数组模板(线段树也写了一遍)
题意: 汉语题就不说题意了,用到单点修改和区间查询(树状数组和线段树都可以) 思路: 树状数组的单点查询,单点修改和区间查询. 树状数组是巧妙运用二进制的规律建树,建树就相当于单点修改.这里面用到一个 ...
- BZOJ 4785 [Zjoi2017]树状数组 | 二维线段树
题目链接 BZOJ 4785 题解 这道题真是令人头秃 = = 可以看出题面中的九条可怜把求前缀和写成了求后缀和,然后他求的区间和却仍然是sum[r] ^ sum[l - 1],实际上求的是闭区间[l ...
- 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)
传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...
- Codeforces 786C Till I Collapse(树状数组+扫描线+倍增)
[题目链接] http://codeforces.com/contest/786/problem/C [题目大意] 给出一个数列,问对于不同的k,将区间划分为几个, 每个区间出现不同元素个数不超过k时 ...
- HDU 4325 离散化+树状数组 或者 不使用树状数组
题意:给出一些花的开放时间段,然后询问某个时间点有几朵花正在开放. 由于ti<1e9,我们需要先将时间离散化,然后将时间点抽象为一个数组中的点,显然,我们需要进行区间更新和单点查询,可以考虑线段 ...
- Codeforces 703D Mishka and Interesting sum(树状数组+扫描线)
[题目链接] http://codeforces.com/contest/703/problem/D [题目大意] 给出一个数列以及m个询问,每个询问要求求出[L,R]区间内出现次数为偶数的数的异或和 ...
随机推荐
- js动画学习笔记
<html> <head> <meta charest="utf-8"> <title>test</title> < ...
- Django performance
Reference: https://impythonist.wordpress.com/2016/02/21/building-high-performance-django-systems/ Th ...
- CentOS标准目录结构
原博:http://www.centoscn.com/CentOS/2014/0424/2861.html/ 最高层root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Gru ...
- 笔记整理--玩转robots协议
玩转robots协议 -- 其他 -- IT技术博客大学习 -- 共学习 共进步! - Google Chrome (2013/7/14 20:24:07) 玩转robots协议 2013年2月8日北 ...
- Grunt安装中遇到的问题汇总
Grunt安装中遇到的问题汇总 1.如果是windows下的dos中安装Grunt,必须以管理员身份登录(第一个坑) 登录方法是: 方法一:开始>所有程序>附件>命令提示符上右键&g ...
- Mysql中常见索引操作
- CentOS 7 部署、连接 数据库mariadb
1.安装mariadb yum -y install mariadb* 2.开启/停止 systemctl start mariadb #启动MariaDB systemctl stop maria ...
- Unity跨平台原理
An ahead-of-time (AOT) compiler is a compiler that implements ahead-of-time compilation. This refers ...
- There is no getter for property named 'userId' in 'class java.lang.String'
[ERROR] 2017-01-18 04:37:06:231 cn.dataenergy.common.CenterHandlerExceptionResolver (CenterHandlerEx ...
- JS可维护性代码
最近在看一本Js的书名叫“Javascript高级程序设计”在里面学到了很多东西,是一本不错的书,非常值得一看. 解耦css/javascript element.style.color=" ...