BZOJ-2829 信用卡凸包
凸包题。
我们先把所有信用卡的四个定点的坐标求出来,然后计算凸包长度,最后加上一个圆的周长就行。
#include <cstdlib> #include <cstdio> #include <cctype> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #define rep(i, l, r) for(int i=l; i<=r; i++) #define clr(x, c) memset(x, c, sizeof(x)) #define lowbit(x) (x&-x) #define maxn 10009 #define maxm 20009 #define inf 0x7fffffff #define k(x) Key[x] #define t(x) Tree[x] using namespace std; inline int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct node{node *l, *r; int sum;} *blank=new(node), *Tree[maxn], *r1[maxn], *r2[maxn]; struct node2{int v, n;} num[maxm]; bool cmp(node2 a, node2 b){return a.v<b.v;} int n, m, V, q[maxn][4], Key[maxm], ln, n1, n2, c[maxm]; char ch[5]; void Build(int l, int r, node*&t) { if (t==blank) t=new(node), t->l=t->r=blank, t->sum=0; if (l==r) return; int mid=(l+r)>>1; Build(l, mid, t->l), Build(mid+1, r, t->r); } void Add(int k, int y, int l, int r, node *u, node*&t) { if (t==blank) t=new(node), t->l=t->r=blank, t->sum=0; t->sum=u->sum+y; if (l==r) return; int mid=(l+r)>>1; if (k<=mid) t->r=u->r, Add(k, y, l, mid, u->l, t->l); else t->l=u->l, Add(k, y, mid+1, r, u->r, t->r); } inline void Change(int t, int k) { node *p; int v=k(t); k(t)=k; for(int x=t; x<=n; x+=lowbit(x)) Add(v, -1, 1, ln, t(x), p=blank), t(x)=p; for(int x=t; x<=n; x+=lowbit(x)) Add(k, 1, 1, ln, t(x), p=blank), t(x)=p; } inline int Query(int l, int r, int k) { n1=n2=0; k--; for(int x=l-1; x; x-=lowbit(x)) r1[++n1]=t(x); for(int x=r; x; x-=lowbit(x)) r2[++n2]=t(x); int L=1, R=ln; while (L<R) { int sum=0, mid=(L+R)>>1; rep(j, 1, n1) sum-=r1[j]->l->sum; rep(j, 1, n2) sum+=r2[j]->l->sum; if (sum<=k) { L=mid+1, k-=sum; rep(j, 1, n1) r1[j]=r1[j]->r; rep(j, 1, n2) r2[j]=r2[j]->r; } else { R=mid; rep(j, 1, n1) r1[j]=r1[j]->l; rep(j, 1, n2) r2[j]=r2[j]->l; } } return c[L]; } void Init(){blank->l=blank->r=blank; blank->sum=0;} int main() { n=V=read(), m=read(); Init(); rep(i, 1, n) num[i].v=read(), num[i].n=i; rep(i, 1, m) { scanf("%s", ch); if (ch[0]=='Q') q[i][0]=1, q[i][1]=read(), q[i][2]=read(), q[i][3]=read(); else { q[i][0]=0, q[i][1]=read(), q[i][2]=read(); ++V, num[V].v=q[i][2], num[V].n=n+i; } } sort(num+1, num+V+1, cmp); c[++ln]=num[1].v, k(num[1].n)=1; rep(i, 2, V) { if (num[i].v != num[i-1].v) c[++ln]=num[i].v; k(num[i].n)=ln; } Build(1, ln, t(0)=blank); rep(i, 1, n) { node *p=t(0); rep(j, i-lowbit(i)+1, i) Add(k(j), 1, 1, ln, p, t(i)=blank), p=t(i); } rep(i, 1, m) if (!q[i][0]) Change(q[i][1], k(n+i)); else printf("%d\n", Query(q[i][1], q[i][2], q[i][3])); return 0; }