JOI春合宿2012 Day2
昨日の問題が簡単に見えるレベル
問題の内容は省略します。
Broadcasting
適当にやったら案の定残念な点数(49点)だった。きゅうりぱないなのっ!
Constellation
凸包とって適当にほげほげしたら 100 点とれた。点数分布がきれいに0点と100点に分かれていてどんびき
#include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef long long i64; const i64 MOD = 1000000007; struct star { i64 x, y, t; star(){ } star(int _x, int _y, int _t) {x = _x; y = _y; t = _t; } }; inline bool operator<(const star& A, const star& B) { return A.x < B.x || (A.x == B.x && A.y < B.y); } int N; star st[100000]; vector<star> cv; int ccw(star& A, star& B, star& C) { i64 tmp = (B.y - A.y) * (C.x - A.x) - (B.x - A.x) * (C.y - A.y); return tmp>0 ? 1 : -1; } void make_convex() { sort(st, st+N); cv.push_back(st[0]); cv.push_back(st[1]); for(int i=2;i<N;i++){ while(cv.size() >= 2 && ccw(cv[cv.size()-2], cv[cv.size()-1], st[i])==-1) cv.pop_back(); cv.push_back(st[i]); } cv.push_back(st[N-2]); for(int i=N-3;i>=0;i--){ while(cv.size() >= 2 && ccw(cv[cv.size()-2], cv[cv.size()-1], st[i])==-1) cv.pop_back(); cv.push_back(st[i]); } cv.pop_back(); //for(int i=0;i<cv.size();i++) printf("%lld %lld\n", cv[i].x, cv[i].y); } int As[200010], Bs[200010]; int main() { scanf("%d", &N); for(int i=0;i<N;i++) scanf("%lld%lld%lld", &(st[i].x), &(st[i].y), &(st[i].t)); make_convex(); i64 ret_a = 1; int arbitrary = 0; int cont1=0, cont2=0; for(int i=0;i<N;i++){ if(st[i].t==0) ++arbitrary; if(st[i].t==1) ++cont1; if(st[i].t==2) ++cont2; } for(int i=0;i<cv.size();i++){ if(cv[i].t==0) --arbitrary; if(cv[i].t==1) --cont1; if(cv[i].t==2) --cont2; } while(arbitrary){ ret_a = (ret_a*2)%MOD; --arbitrary; } cont1 = !!cont1; cont2 = !!cont2; i64 ret = 0; int M = cv.size(); As[0] = 0; for(int i=1;i<=2*M;i++) As[i] = As[i-1] + ((cv[i%M].t==1) ? 1 : 0); Bs[0] = 0; for(int i=1;i<=2*M;i++) Bs[i] = Bs[i-1] + ((cv[i%M].t==2) ? 1 : 0); for(int i=0;i<M;i++){ int jMin, jMax; jMin = (lower_bound(As, As+(2*M+1), As[i+M]) - As) - i; jMax = (upper_bound(Bs, Bs+(2*M+1), Bs[i]) - Bs) - i - 1; jMin = max(jMin, 1); jMax = min(jMax, M-1); ret += (ret_a * (i64)max(0, jMax - jMin + 1)) % MOD; ret %= MOD; } ret += 2 * (ret_a - 1) + cont1 + cont2; for(int i=0;i<M;i++){ if(cv[i].t==1){ ret -= ret_a - 1 + cont1; break; } } for(int i=0;i<M;i++){ if(cv[i].t==2){ ret -= ret_a - 1 + cont2; break; } } printf("%lld\n", ret % MOD); return 0; }
Rotate
思いつかなくて「やるだけ」やったら 10 点で絶望。
コードは載せるまでもない
リストの張替え O(QN) で満点が取れるらしい。定数倍最適化で 80 点が取れるらしくてどんびき