CF GYM. 102861M. Machine Gun(主席树)
简直是傻了做的时候连主席树都不会用了
容易发现,合法的点\((x,y)\)若满足询问\((qx,qy)\),则需满足\(2y-x\leq 2qy-qx,\ 2y+x\geq 2qy+qx\),将点\((x,y)\)变为\((2y-x,2y+x)\),就是一个二维偏序。
强制在线,最简单的办法就是线段树套线段树(TLE on #2),或是按\(x\)排序后对\(y\)轴建主席树。
还有一个在线方法是区间树(std,但是我的TLE on #5/whl,是我太菜了):换一下表示方式,题意等价于求与\([2qy+qx,2qy-qx]\)相交的所有区间,用线段树+区间树可以实现(纯区间树应该做不了吧,所以常数很大)。区间树见这儿,很裸。
记一下主席树的细节:纵坐标\(y_i\)用\((n+1)\times y_i+i\)进行储存和离散化,这样一是没有可持久化要存\(vector\)的问题,二是主席树\(Query\)出来的答案就是按标号排好序的(不需再排序)。
为了方便可以用\((y_i<<18)+i\),这样某个\(y\)位置的编号就是\(y\&((1<<18)-1)\)。(最好用\(2y+x\)作为\(y\)让\(y\)做编号时为正数?)
主席树:
//296ms 19600KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define pb emplace_back
#define mod 1000000007
typedef long long LL;
const int N=1e5+5,M=(1<<18)-1;
int root[N],cnt,Ans[N];
LL X[N],Y[N],pw[N];
struct Node
{
LL x,y;
bool operator <(const Node &a)const
{
return x<a.x;
}
}A[N];
struct President_Tree
{
#define S N*19
#define ls son[x][0]
#define rs son[x][1]
#define lson ls,son[y][0],l,m
#define rson rs,son[y][1],m+1,r
int tot,son[S][2];
#undef S
void Insert(int &x,int y,int l,int r,int p)
{
x=++tot;
if(l==r) return;
int m=l+r>>1;
p<=m?(rs=son[y][1],Insert(lson,p)):(ls=son[y][0],Insert(rson,p));
}
void Query(int x,int l,int r,int p)//p~N
{
if(!x) return;
if(l==r) {Ans[++cnt]=Y[l]&M; return;}
int m=l+r>>1;
p<=m && (Query(ls,l,m,p),0);
Query(rs,m+1,r,p);
}
}T;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int Find(int r,LL v)//the first num satisfying >=v
{
int l=1,mid;
while(l<r)
if(Y[mid=l+r>>1]<v) l=mid+1;
else r=mid;
return l;
}
int Find2(int r,LL v)//the first num satisfying <=v
{
if(X[1]>v) return 0;
int l=1,mid,ans=0;
while(l<=r)
if(X[mid=l+r>>1]<=v) l=mid+1,ans=mid;
else r=mid-1;
return ans;
}
int main()
{
int n=read(),Q=read();
pw[0]=1;
for(int i=1; i<=n; ++i) pw[i]=pw[i-1]*5782344%mod;
for(int i=1; i<=n; ++i)
{
LL x=read(),y=read();
A[i].x=2*y-x, Y[i]=A[i].y=((2*y+x)<<18)+i;
}
std::sort(A+1,A+1+n), std::sort(Y+1,Y+1+n);
for(int i=1; i<=n; ++i) X[i]=A[i].x;
for(int i=1; i<=n; ++i) T.Insert(root[i],root[i-1],1,n,Find(n,A[i].y));
for(int p=0; Q--; )
{
LL x=-1-((p+read())%mod),y=(p+read())%mod;
if(2*y+x>Y[n]) {printf("%d\n",p=0); continue;}
int R1=Find2(n,2*y-x),L2=Find(n,(2*y+x)<<18);
cnt=0, T.Query(root[R1],1,n,L2);
LL res=0;
std::sort(Ans+1,Ans+1+cnt);
LL *pw_=pw;
for(int *a=Ans+1,*lim=Ans+cnt+1; a!=lim; ++a,++pw_) res+=(*a)*(*pw_)%mod;
p=(int)(res%mod), printf("%d\n",p);
}
return 0;
}
区间树:
/*
TLE on #5
*/
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define pb emplace_back
#define mod 1000000007
#define Vec std::vector<Node>
typedef long long LL;
const int N=(1e5+5)*2;//*2
#define De 0
struct Node
{
int l,r,id;
bool operator <(const Node &x)const
{
return l!=x.l?l<x.l:r<x.r;
}
bool operator <=(const Node &x)const
{
id<x.id;
}
bool operator !=(const Node &x)const
{
return id!=x.id;
}
void P() {printf("%d~%d %d\n",l,r,id);}
}node[N];
std::vector<int> Ans,Ans2;
//inline bool Cmp(const Node &a,const Node &b)
//{
// return a.l!=b.l?a.l<b.l:a.r<b.r;
//}
inline void Merge(std::vector<int> &rt,std::vector<int> &a,std::vector<int> &b)
{
std::vector<int> tmp;
auto l=a.begin(),le=a.end(),r=b.begin(),re=b.end();
while(l!=le&&r!=re)
if(*l<*r) tmp.pb(*l++);
else if(*l>*r) tmp.pb(*r++);
else tmp.pb(*l++), r++;
while(l!=le) tmp.pb(*l++);
while(r!=re) tmp.pb(*r++);
int las=0; std::vector<int>().swap(rt);//先用完a,b再清空!
for(auto i:tmp)
if(i!=las) rt.pb(i), las=i;
}
struct Segment_Tree
{
#define S N<<2
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
int son[S][2];
std::vector<int> vec[S];
#undef S
void Insert(int l,int r,int rt,int p,int id)
{
if(l==r) {vec[rt].pb(id); return;}
int m=l+r>>1;
p<=m?Insert(lson,p,id):Insert(rson,p,id);
}
void Maintain(int l,int r,int rt)
{
if(l==r) return;
int m=l+r>>1;
Maintain(lson), Maintain(rson), Merge(vec[rt],vec[ls],vec[rs]);
}
void Query(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) {Merge(Ans,Ans,vec[rt]); return;}
int m=l+r>>1;
if(L<=m) Query(lson,L,R);
if(m<R) Query(rson,L,R);
}
#undef ls
#undef rs
#undef lson
#undef rson
}ST;
struct Interval_Tree
{
#define S N*19//N<<2
#define ls son[rt][0]
#define rs son[rt][1]
int tot,A[N<<1],son[S][2],center[S];
Vec Sa[S],Sb[S];
#undef S
void Build(int &rt,Vec &va,Vec &vb)
{
int t=va.size();
if(!t) {rt=0; return;}
int cnt=0; !rt&&(rt=++tot);
for(auto i:va) A[++cnt]=i.l, A[++cnt]=i.r;
std::nth_element(A+1,A+t,A+1+cnt);//O(n)找中位数
int xc=A[t]; center[rt]=xc;
// if(De)
// {
// printf("\nrt:%d\nA:",rt);
// for(auto i:va) i.P();
// printf("B:"); for(auto i:vb) i.P();
// printf("center:%d\n",xc);
// }
Vec val,vbl,var,vbr;
for(auto i:va)
if(i.r<xc) val.pb(i);
else if(i.l>xc) var.pb(i);
else Sa[rt].pb(i);
for(auto i:vb)
if(i.r<xc) vbl.pb(i);
else if(i.l>xc) vbr.pb(i);
else Sb[rt].pb(i);
Build(ls,val,vbl), Build(rs,var,vbr);
}
#define Update() std::sort(tmp.begin(),tmp.end()), Merge(Ans2,Ans2,tmp)
// #define Update() rt
void Query(int rt,int p)
{
if(!rt) return;
std::vector<int> tmp;
if(p==center[rt])
{
for(auto i:Sa[rt]) tmp.pb(i.id);
Update();
}
else if(p<center[rt])
{
for(auto i:Sa[rt])
if(i.l<=p) tmp.pb(i.id); else break;
Update(), Query(ls,p);
}
else
{
for(auto i:Sb[rt])
if(i.r>=p) tmp.pb(i.id); else break;
Update(), Query(rs,p);
}
}
}IT;
struct Array
{
int cnt;
LL A[N],B[N],Ref[N];
int Find(LL v)
{
if(Ref[cnt]<v) return cnt+1;
int l=1,r=cnt,mid;
while(l<r)
if(Ref[mid=l+r>>1]<v) l=mid+1;
else r=mid;
return l;
}
int Find2(LL v)
{
if(Ref[1]>v) return 0;
int l=1,r=cnt,mid,ans=0;
while(l<=r)
if(Ref[mid=l+r>>1]<=v) l=mid+1,ans=mid;
else r=mid-1;
return ans;
}
void Discrete(const int n)
{
const int m=n<<1;
for(int i=1; i<=n; ++i) Ref[(i<<1)-1]=A[i], Ref[i<<1]=B[i];
std::sort(Ref+1,Ref+1+m);
cnt=1;
for(int i=2; i<=m; ++i) if(Ref[i]!=Ref[i-1]) Ref[++cnt]=Ref[i];
for(int i=1; i<=n; ++i) A[i]=Find(A[i]), B[i]=Find(B[i]);
}
}A;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
bool cmpl(const Node &a,const Node &b)
{
return a.l<b.l;
}
bool cmpr(const Node &a,const Node &b)
{
return a.r>b.r;
}
int main()
{
int n=read(),Q=read();
for(int i=1; i<=n; ++i)
{
LL x=read(),y=read();
A.A[i]=2*y-x, A.B[i]=2*y+x;
}
A.Discrete(n);
//ST
int cnt=A.cnt;
for(int i=1; i<=n; ++i)
{
node[i]=(Node){A.A[i],A.B[i],i};
ST.Insert(1,cnt,1,A.A[i],i), ST.Insert(1,cnt,1,A.B[i],i);
}
ST.Maintain(1,cnt,1);
//IT
Vec a,b; int root=0;
for(int i=1; i<=n; ++i) a.pb(node[i]),b.pb(node[i]);
std::sort(a.begin(),a.end(),cmpl), std::sort(b.begin(),b.end(),cmpr);
IT.Build(root,a,b);
//Query
for(int p=0; Q--; )
{
LL x=-1-((p+read())%mod),y=(p+read())%mod;
int L=A.Find(2*y+x),R=A.Find2(2*y-x);
std::vector<int>().swap(Ans), std::vector<int>().swap(Ans2);
//
if(L<=R)
{
ST.Query(1,cnt,1,L,R), IT.Query(root,L);
// if(De) {puts("ST Query:"); for(auto a:Ans) printf("%d ",a); De&&pc('\n');}
std::vector<int> tmp;
for(auto i:Ans2) if(node[i].l<=L && node[i].r>=R) tmp.pb(i);
// if(De) {puts("IT Query:"); for(auto a:tmp) printf("%d ",a); De&&pc('\n');}
Merge(Ans,Ans,tmp);
}
//
LL res=0,t=1; int las=-1;
for(auto a:Ans)
if(a!=las) res+=a*t%mod, t=t*5782344%mod, las=a;
printf("%d\n",p=(int)(res%mod));//(int)(res%mod)!=(int)res%mod!
}
return 0;
}
线段树套线段树:
/*
TLE on #2
*/
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define mod 1000000007
typedef long long LL;
const int N=1e5+5;
//const LL M1=2e9,M2=3000000000ll,M3=1e9;
std::vector<int> Ans;
struct Segment_Tree_2D
{
#define S N*170
#define ls son[x][0]
#define rs son[x][1]
#define lson ls,l,m
#define rson rs,m+1,r
int tot,cntB,son[S][2],p,id,L,R;
std::vector<int> vec[S];
#undef S
void Ins(int &x,int _p,int _id)
{
p=_p, id=_id, Insert(x,1,cntB);
}
void Insert(int &x,int l,int r)
{
if(!x) x=++tot; vec[x].emplace_back(id);
if(l==r) return;
int m=l+r>>1; p<=m?Insert(lson):Insert(rson);
}
void Qry(int x,int _L,int _R)
{
L=_L, R=_R, Query(x,1,cntB);
}
void Query(int x,int l,int r)
{
if(!x) return;
if(L<=l && r<=R)
{
for(auto a:vec[x]) Ans.emplace_back(a);
return;
}
int m=l+r>>1;
if(L<=m) Query(lson);
if(m<R) Query(rson);
}
#undef ls
#undef rs
#undef lson
#undef rson
};
struct Segment_Tree_1D
{
#define S N
#define ls son[x][0]
#define rs son[x][1]
#define lson ls,l,m
#define rson rs,m+1,r
int tot,cntA,son[S][2],root[S],id,p1,p2,L1,R1,L2,R2;
Segment_Tree_2D T;
#undef S
void Ins(int &x,int _p1,int _p2,int _id)
{
p1=_p1, p2=_p2, id=_id, Insert(x,1,cntA);
}
void Insert(int &x,int l,int r)
{
if(!x) x=++tot; T.Ins(root[x],p2,id);
if(l==r) return;
int m=l+r>>1; p1<=m?Insert(lson):Insert(rson);
}
void Qry(int x,int _L1,int _R1,int _L2,int _R2)
{
if(_L1<=_R1 && _L2<=_R2)
L1=_L1, R1=_R1, L2=_L2, R2=_R2, Query(x,1,cntA);
}
void Query(int x,int l,int r)
{
if(!x) return;
// printf("Query(%d %lld~%lld %lld~%lld %lld~%lld)\n",x,l,r,L1,R1,L2,R2);
if(L1<=l && r<=R1)
{
T.Qry(root[x],L2,R2);
return;
}
int m=l+r>>1;
if(L1<=m) Query(lson);
if(m<R1) Query(rson);
}
}T;
struct Array
{
int cnt,val[N];
LL A[N],Ref[N];
int Find(LL v)
{
if(Ref[cnt]<v) return cnt+1;
int l=1,r=cnt,mid;
while(l<r)
if(Ref[mid=l+r>>1]<v) l=mid+1;
else r=mid;
return l;
}
int Find2(LL v)
{
if(Ref[1]>v) return 0;
int l=1,r=cnt,mid,ans=0;
while(l<=r)
if(Ref[mid=l+r>>1]<=v) l=mid+1,ans=mid;
else r=mid-1;
return ans;
}
void Discrete(const int n)
{
for(int i=1; i<=n; ++i) Ref[i]=A[i];
std::sort(Ref+1,Ref+1+n);
cnt=1;
for(int i=2; i<=n; ++i) if(Ref[i]!=Ref[i-1]) Ref[++cnt]=Ref[i];
for(int i=1; i<=n; ++i) val[i]=Find(A[i]);
}
}A,B;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
#define De 0
int main()
{
int n=read(),Q=read();
int root=0;
for(int i=1; i<=n; ++i)
{
LL x=read(),y=read();
A.A[i]=x+2*y, B.A[i]=2*y-x;
}
A.Discrete(n), B.Discrete(n);
int cntA=A.cnt,cntB=B.cnt;
T.cntA=A.cnt, T.T.cntB=B.cnt;
for(int i=1; i<=n; ++i) T.Ins(root,A.val[i],B.val[i],i);
for(int p=0; Q--; )
{
LL x=-1-((p+read())%mod),y=(p+read())%mod;
// De&&printf("(%d,%d)\n",x,y);
int L1=A.Find(2*y+x),R1=cntA,L2=1,R2=B.Find2(2*y-x);
// De&&printf("%d~%d %d~%d %d %d\n",L1,R1,L2,R2,2*y+x,2*y-x);
Ans.clear(), T.Qry(root,L1,R1,L2,R2);
LL res=0,t=1;
std::sort(Ans.begin(),Ans.end());
if(De) for(auto a:Ans) printf("%d ",a); De&&pc('\n');
for(auto a:Ans) res+=a*t%mod, t=t*5782344%mod;
p=(int)(res%mod);
printf("%d\n",p);
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------