# [二进制分组 线段树 || 点分治 分治] UOJ #191 【集训队互测2016】Unknown

459人阅读 评论(1)

#### 二进制分组做法

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cassert>
#define pb push_back
using namespace std;
typedef double ld;
typedef long long ll;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
}
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=550005;
const ld PI=acos(-1.0);

struct PP{
ll x,y;
PP(ll x=0,ll y=0):x(x),y(y) { }
friend PP operator + (PP A,PP B){ return PP(A.x+B.x,A.y+B.y); }
friend PP operator - (PP A,PP B){ return PP(A.x-B.x,A.y-B.y); }
friend ll operator * (PP A,PP B){ return A.x*B.y-A.y*B.x; }
friend ld Ang(PP A,PP B){
ld ang=atan2(B.y-A.y,B.x-A.x);
return (B.y<A.y&&B.x<=A.x)?ang+2*PI:ang;
}
bool operator < (const PP &B) const{
return x==B.x?y<B.y:x<B.x;
}
};

vector<int> hull[N<<1];

int tmp[N]; int cnt,pnt;

PP pp[N];

int ncnt;
int last[N];
int ls[N<<1],rs[N<<1],lp[N<<1],lb[N<<1],rb[N<<1];
int tag[N<<1];

inline void BH(int x,int l,int r){
hull[x].clear();
if (l==r) { hull[x].pb(l); return; }
int p=0,q=0; cnt=0;
//assert(tag[ls[x]] && tag[rs[x]]);
for (;p<hull[ls[x]].size() || q<hull[rs[x]].size();){
int t;
if (p==hull[ls[x]].size())
t=hull[rs[x]][q++];
else if (q==hull[rs[x]].size())
t=hull[ls[x]][p++];
else if (pp[hull[ls[x]][p]].x<pp[hull[rs[x]][q]].x)
t=hull[ls[x]][p++];
else
t=hull[rs[x]][q++];
if (cnt && pp[t].x==pp[tmp[cnt]].x){
if (pp[tmp[cnt]].y<pp[t].y) tmp[cnt]=t;
}else
tmp[++cnt]=t;
}
pnt=0;
for (int i=1;i<=cnt;i++){
while (pnt>=2 && (pp[tmp[i]]-pp[tmp[pnt]])*(pp[tmp[pnt]]-pp[tmp[pnt-1]])<=0) pnt--;
tmp[++pnt]=tmp[i];
}
for (int i=1;i<=pnt;i++)
hull[x].pb(tmp[i]);
}
inline ll query(int x,PP p){
int L=-1,R=hull[x].size()-1,MID;
while (L+1<R){
MID=(L+R)>>1;
if ((pp[hull[x][MID+1]]-pp[hull[x][MID]])*p<=0)
L=MID;
else
R=MID;
}
return p*pp[hull[x][R]];
}

inline void Build(int &x,int l,int r,int d=0){
x=++ncnt; lp[x]=last[d]; last[d]=x; lb[x]=l; rb[x]=r;
if (l==r) return;
int mid=(l+r)>>1;
Build(ls[x],l,mid,d+1); Build(rs[x],mid+1,r,d+1);
}

inline void Add(int x,int l,int r,int t){
if (t==r && lp[x]) tag[lp[x]]=1,BH(lp[x],lb[lp[x]],rb[lp[x]]);
if (l==r) return;
int mid=(l+r)>>1;
}
inline void Del(int x,int l,int r,int t){
tag[x]=0;
if (l==r) return;
int mid=(l+r)>>1;
if (t<=mid) Del(ls[x],l,mid,t);
else Del(rs[x],mid+1,r,t);
}

ll Ret;
inline void Query(int x,int l,int r,int ql,int qr,PP p){
if (ql<=l && r<=qr && (tag[x] || l==r)){
if (l<r)
Ret=max(Ret,query(x,p));
else
Ret=max(Ret,p*pp[l]);
return;
}
int mid=(l+r)>>1;
if (ql<=mid) Query(ls[x],l,mid,ql,qr,p);
if (qr>mid) Query(rs[x],mid+1,r,ql,qr,p);
}

const int P=998244353;

int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
int order,x,y,l,r;
while (1){
int tot=0,rt; int n=1; while (n<m) n<<=1;
ncnt=0;
Build(rt,1,n);
int ans=0;
while (m--){
if (order==1)
else if (order==2)
Del(1,1,n,tot--);
else{
Query(1,1,n,l,r,PP(x,y));
ans^=((Ret%P)+P)%P;
}
}
printf("%d\n",ans);
for (int i=1;i<=ncnt;i++) ls[i]=rs[i]=lp[i]=last[i]=tag[i]=0,hull[i].clear();
}
return 0;
}


#### 操作树上点分治

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
//typedef pair<int,int> abcd;
#define abcd PP
#define first x
#define second y
typedef double ld;
typedef long long ll;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
}
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=300005;
const ld PI=acos(-1.0);

struct PP{
ll x,y;
PP(ll x=0,ll y=0):x(x),y(y) { }
friend PP operator + (PP A,PP B){ return PP(A.x+B.x,A.y+B.y); }
friend PP operator - (PP A,PP B){ return PP(A.x-B.x,A.y-B.y); }
friend ll operator * (PP A,PP B){ return A.x*B.y-A.y*B.x; }
bool operator < (const PP &B) const{
return x==B.x?y<B.y:x<B.x;
}
};

struct edge{
int v,next;
}G[N<<1];
}
#define V G[p].v
int ncnt; //int Stack[N],Pnt;
PP pp[N];

int fat[N],depth[N];

bool del[N];

int minv=1<<30,size[N],sum,rt;
inline void Root(int u,int fa){
size[u]=1; int maxv=0;
if (V!=fa && !del[V])
Root(V,u),size[u]+=size[V],maxv=max(maxv,size[V]);
maxv=max(maxv,sum-size[u]);
if (minv>maxv) minv=maxv,rt=u;
}

//vector<int> que[N];
int tot,uu[N]/*,vv[N]*/; ll ans[N];
PP qp[N];

bool cmp(abcd x,abcd y){
return qp[x.second]*qp[y.second]<=0;
}

PP po[N]; int pcnt; PP tmpp[N];
abcd qq[N]; int qcnt; //abcd tmp[N];

inline void divide(int l,int r,int ql,int qr,int &hcnt){
if (l==r){
sort(qq+ql,qq+qr+1,cmp);
for (int i=ql;i<=qr;i++)
ans[qq[i].second]=max(ans[qq[i].second],qp[qq[i].second]*po[l]);
hcnt=1;
return;
}
int lh=0,rh=0; int mid=(l+r)>>1;
int lp=ql-1,rp=qr+1;
for (int i=ql;i<=qr;i++)
if (qq[i].first<=mid) tmpp[++lp]=qq[i]; else tmpp[--rp]=qq[i];
for (int i=ql;i<=qr;i++) qq[i]=tmpp[i];

divide(l,mid,ql,lp,lh);
divide(mid+1,r,rp,qr,rh);

int j=1;
for (int i=rp;i<=qr;i++){
while (j+1<=lh && qp[qq[i].second]*po[l+j-1]<qp[qq[i].second]*po[l+(j+1)-1])
j++;
ans[qq[i].second]=max(ans[qq[i].second],qp[qq[i].second]*po[l+j-1]);
}

if (!(l==1 && r==pcnt)){
int p=1,q=1; int cnt=0;
while (p<=lh || q<=rh){
PP t;
if (p==lh+1 || (q<=rh && po[mid+q].x<=po[l+p-1].x))
t=po[mid+(q++)];
else
t=po[l+(p++)-1];
if (!cnt || tmpp[cnt].x!=t.x)
tmpp[++cnt]=t;
else
tmpp[cnt].y=max(tmpp[cnt].y,t.y);
}
int pnt=0;
for (int i=1;i<=cnt;i++){
while (pnt>=2 && (tmpp[i]-tmpp[pnt])*(tmpp[pnt]-tmpp[pnt-1])<=0) pnt--;
tmpp[++pnt]=tmpp[i];
}
hcnt=pnt;
for (int i=1;i<=pnt;i++) po[l+i-1]=tmpp[i];

pnt=0,p=ql,q=rp;
while (p<=lp || q<=qr){
if (p==lp+1 || (q<=qr && qp[qq[q].second]*qp[qq[p].second]<0))
tmpp[++pnt]=qq[q++];
else
tmpp[++pnt]=qq[p++];
}
for (int i=1;i<=pnt;i++) qq[ql+i-1]=tmpp[i];
}
}

int R,Gg;

inline void dfs(int u,int fa){
//for (int i:que[u])
int i=V;
if (depth[uu[i]]<=depth[Gg])
qq[++qcnt]=abcd(depth[Gg]-max(depth[uu[i]],depth[R])+1,i);
}
if (V!=fa && !del[V])
dfs(V,u);
}

inline void Divide(int u,int S){
sum=S; minv=1<<30; Root(u,0);
R=u; Gg=rt;
pcnt=0; int t=Gg; while (t!=R) po[++pcnt]=pp[t],t=fat[t]; po[++pcnt]=pp[R];
qcnt=0; dfs(Gg,fat[Gg]);
int tmp; if (qcnt) divide(1,pcnt,1,qcnt,tmp);

int tt=Gg;
del[Gg]=1;
if (Gg^R) Divide(u,S-size[Gg]);
if (!del[V])
Divide(V,size[V]);
}

const int P=998244353;

int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
int m; int order,l,r,x,y;
while (1){
read(m); if (!m) break; int cur=0,Pnt=0,*Stack=size;tot=ncnt=0;
Stack[++Pnt]=++ncnt; cur=ncnt;
while (m--){
if (order==1){
depth[ncnt]=depth[fat[ncnt]]+1;
cur=ncnt; Stack[++Pnt]=ncnt;
}else if (order==2){
cur=fat[cur]; Stack[Pnt--]=0;
}else if (order==3){
++tot; ans[tot]=-1LL<<60; qp[tot]=PP(x,y);  uu[tot]=Stack[l+1];
//vv[tot]=Stack[r+1]; que[vv[tot]].pb(tot);
//que[Stack[r+1]].pb(tot);
}
}
Divide(1,ncnt);
int Ans=0;
for (int i=1;i<=tot;i++)
Ans^=(ans[i]%P+P)%P;
printf("%d\n",Ans);
}
return 0;
}

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：337090次
• 积分：12744
• 等级：
• 排名：第1262名
• 原创：975篇
• 转载：3篇
• 译文：0篇
• 评论：54条
文章分类
阅读排行
最新评论