POJ 2991線分ツリー
10449 ワード
POJ 2991タイトルリンク:http://poj.org/problem?id=2991 題意:n個の初期線分を与え、線分の先頭と末尾がつながっている.最初はy軸にありました今は回転操作をするたびに.操作時には、前u個の点が動かず、第u個の点がu-1点に対して回転し、u点の後ろの点がuに対する位置も動かない.構想:セグメントツリー、区間更新.操作ごとにuおよびuの後のすべての点を更新することに相当するため、x、y、angle、flagの4つの値があり、それぞれ横座標、縦座標、角度、遅延フラグを表す点構造を保存する.更新方法は奇抜で、具体的にはpush_を参照してください.down,push_up,func関数ですが,遅延マーキングの考え方でもあります.ソース:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 10000 + 5;
const double PI = acos(-1.0);
int n, q;
double x[MAXN * 4], y[MAXN * 4];
int angle[MAXN * 4];
int flag[MAXN * 4];
int a[MAXN * 4];
void func(int o, int ang) /// { double tx = x[o], ty = y[o]; x[o] = tx * cos(ang * PI / 180.0) - ty * sin(ang * PI / 180.0);
y[o] = tx * sin(ang * PI / 180.0) + ty * cos(ang * PI / 180.0);
angle[o] = (angle[o] + ang) % 360;
flag[o] = (flag[o] + ang) % 360;
}
void push_up(int o)
{
x[o] = x[o << 1] + x[(o << 1) | 1];
y[o] = y[o << 1] + y[(o << 1) | 1];
}
void push_down(int o)
{
if(flag[o]){
func(o << 1, flag[o]);
func((o << 1) | 1, flag[o]);
flag[o] = 0;
}
}
void build(int l, int r, int o)
{
x[o] = 0;
angle[o] = flag[o] = 0;
if(l == r){
y[o] = a[l];
}
else{
int mid = (l + r) >> 1;
build(l, mid, o << 1);
build(mid + 1, r, (o << 1) | 1);
push_up(o);
}
}
int query(int u, int l, int r, int o)
{
// printf("u = %d, l = %d, r = %d, o = %d, angle = %d, flag = %d
", u, l, r, o, angle[o], flag[o]);
if(l == r) return angle[o];
else{
push_down(o);
int mid = (l + r) >> 1;
int ang;
if(u <= mid) ang = query(u, l, mid, o << 1);
else ang = query(u, mid + 1, r, (o << 1) | 1);
push_up(o);
return ang;
}
}
void update(int l, int r, int ang, int L, int R, int o)
{
// printf("o = %d, l = %d, r = %d, L = %d, R = %d, ang = %d
", o, l, r, L, R, ang);
if(l <= L && r >= R){
func(o, ang);
}
else{
push_down(o);
int mid = (L + R) >> 1;
if(l <= mid) update(l, r, ang, L, mid, o << 1);
if(mid < r) update(l, r, ang, mid + 1, R, (o << 1) | 1);
push_up(o);
}
// printf("o = %d, angle[o] = %d, flag[o] = %d
", o, angle[o], flag[o]);
}
int main()
{
// freopen("data.txt", "r", stdin);
int f = 1;
while(scanf("%d%d", &n, &q) != EOF){
for(int i = 1 ; i <= n ; i++) scanf("%d", a + i);
if(f) f = 0;
else printf("
");
build(1, n, 1);
// printf("x[1] = %.2f y[1] = %.2f
", x[1], y[1]);
while(q--){
int u, v;
scanf("%d%d", &u, &v);
int a1 = query(u, 1, n, 1);
int a2 = query(u + 1, 1, n, 1);
// int ang = query(u, 1, n, 1) - 180 + v - query(u + 1, 1, n, 1);
int ang = (v - (a2 - a1 + 180 + 360) % 360) % 360;
// printf("ang = %d, a1 = %d, a2 = %d
", ang, a1, a2);
// ang = (ang + 360) % 360;
update(u + 1, n, ang, 1, n, 1);
printf("%.2f %.2f
", x[1], y[1]);
}
}
return 0;
}