这道题一上手就知道怎么做了= =

直接求出原光路和从目标点出发的光路,求这些光路的交点就行了

然后用树状数组+扫描线或函数式线段树就能过了= =

大量的离散+模拟+二分什么的特别恶心,考试的时候是想到了不过被代码难度吓到了根本不想写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 (树状数组+扫描线/函数式线段树)的更多相关文章

  1. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

  2. 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  3. bzoj4785:[ZJOI2017]树状数组:二维线段树

    分析: "如果你对树状数组比较熟悉,不难发现可怜求的是后缀和" 设数列为\(A\),那么可怜求的就是\(A_{l-1}\)到\(A_{r-1}\)的和(即\(l-1\)的后缀减\( ...

  4. HDU - 1166 树状数组模板(线段树也写了一遍)

    题意: 汉语题就不说题意了,用到单点修改和区间查询(树状数组和线段树都可以) 思路: 树状数组的单点查询,单点修改和区间查询. 树状数组是巧妙运用二进制的规律建树,建树就相当于单点修改.这里面用到一个 ...

  5. BZOJ 4785 [Zjoi2017]树状数组 | 二维线段树

    题目链接 BZOJ 4785 题解 这道题真是令人头秃 = = 可以看出题面中的九条可怜把求前缀和写成了求后缀和,然后他求的区间和却仍然是sum[r] ^ sum[l - 1],实际上求的是闭区间[l ...

  6. 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)

    传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...

  7. Codeforces 786C Till I Collapse(树状数组+扫描线+倍增)

    [题目链接] http://codeforces.com/contest/786/problem/C [题目大意] 给出一个数列,问对于不同的k,将区间划分为几个, 每个区间出现不同元素个数不超过k时 ...

  8. HDU 4325 离散化+树状数组 或者 不使用树状数组

    题意:给出一些花的开放时间段,然后询问某个时间点有几朵花正在开放. 由于ti<1e9,我们需要先将时间离散化,然后将时间点抽象为一个数组中的点,显然,我们需要进行区间更新和单点查询,可以考虑线段 ...

  9. Codeforces 703D Mishka and Interesting sum(树状数组+扫描线)

    [题目链接] http://codeforces.com/contest/703/problem/D [题目大意] 给出一个数列以及m个询问,每个询问要求求出[L,R]区间内出现次数为偶数的数的异或和 ...

随机推荐

  1. 【转】安卓必备Java基础

    [转]http://www.zhihu.com/question/19937886(里面提到的知识点的链接) 1. Java 语言基础 谈到Java 语言基础学习的书籍,大家肯定会推荐Bruce Ec ...

  2. 如何备份、还原或迁移 WhatsApp 的信息和资料?

    WhatsApp 会在每天清晨 2 点钟自动创建本地备份文件并将备份文件存储在手机系统设置的文件夹中. Google 云端硬盘 您可以备份对话记录和媒体到 Google 云端硬盘以便日后更换手机时仍可 ...

  3. 三 APPIUM Android自动化 测试初体验

    1.创建一个maven项目 成功新建工程: 编辑pom.xml,在<dependencies></dependencies>下添加appium相关依赖: <depende ...

  4. 使用布局(Layout资源)

    实际上从我们学习第一个Android应用开始,已经开始接触Android的Layout资源了,因此此处不会详细介绍Android Layout资源的知识,会对Layout资源进行简单的归纳. Layo ...

  5. endnote X7使用方法

    网页版的endnote不能添加新模版,只能用模版库里的那些,所以转而试试离线版客户端. 1.下载安装完以后(下载地址就不给了,网上有很多),在word里可以看到顶栏有插件,如果你同时也安装了在线版本, ...

  6. --@angularJS--指令与控制器之间的交互demo

    1.index.html: <!DOCTYPE HTML><html ng-app="app"><head>    <title>c ...

  7. Eclipse 打开文件所在文件夹

    右击文件 > Show In > System Explorer

  8. word中利用宏替换标点标点全角与半角

    Alt+F11,然后插入-模块: 复制下面代码到编辑窗口: Sub 半角标点符号转换为全角标点符号() '中英互译文档中将中文段落中的英文标点符号替换为中文标点符号 Dim i As Paragrap ...

  9. java如何获取本机IP

    java如何获取本机IP import java.net.*; public class Test6 { public static void main(String[] args) { // TOD ...

  10. Lazy.js : 让 JavaScript 变懒

    Lazy.js : 让 JavaScript 变懒 http://segmentfault.com/a/1190000000358463