[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;
}
原文地址:https://www.cnblogs.com/New-Godess/p/4348899.html