T1 点点的圈圈
因为只有包含关系和不相交关系,就可以根据包含关系\(O(n^2)\)建树,\(O(n)\)跑树形dp
考虑优化建树,把一个圆看成一个正方形然后做扫描线,线段树每个节点维护set,存纵坐标在这个区间的正方形的编号
需要判四个角,暴力跳就行了
大多数情况下复杂度\(O(n\log^2n)\)
T2 点点的计算
发现\(T(n,k)=nC(n-1,k-1)\)
然后继续观察,我们要求的是\(lcm(n-k+1,n-k+2 ...n)\)
构造一个数组\(G_i\),使得上式等于\(\prod_{i=n-k+1}^{n}G_i\)
考虑已经构造出 n-1 时的G数组,先在\(G_n\)处插入 n
这样显然不一定合法,因为n的质因子在前面出现过,这样会重复
将n质因数分解,计算\(p^k\),q设为k
如果之前出现了\(p^r\),若r>=q,使r减q,否则r->0,q也减r
可以给每种质数开个栈,可持久化线段树维护即可
复杂度\(O(m\log^2m + t\log m)\)
T3
没改出来
代码
T1
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
const int N=1e5+11;
const int inf=1e9;
struct pot_{int xl,xr,yd,yp,x,y,r,w;}pot[N];
struct tree{int l,r;set<int> st;}tre[8*N];
bool vis[N];
int n;
int f[N];
int lsh[2*N],num;
vector<int> vi[2*N],vo[2*N],vct[N];
il int pd(int x){return x*x;}
il int min_(int x,int y){return x>y?y:x;}
il int max_(int x,int y){return x>y?x:y;}
il bool cmp(pot_ a,pot_ b){return a.r<b.r;}
il bool jud(pot_ a,pot_ b){return pd(b.y-a.y)+pd(b.x-a.x)-pd(b.r)<0;}
il int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
void build(int i,int l,int r)
{
tre[i].l=l,tre[i].r=r;
tre[i].st.clear();
if(l==r) return;
int mid=(l+r)>>1;
build(i<<1,l,mid),build(i<<1|1,mid+1,r);
return;
}
void insert(int i,int l,int r,int id,bool jd)
{
if(tre[i].l>=l&&tre[i].r<=r){if(jd) tre[i].st.insert(id);else tre[i].st.erase(id);return;}
int mid=(tre[i].l+tre[i].r)>>1;
if(l<=mid) insert(i<<1,l,r,id,jd);
if(r>mid) insert(i<<1|1,l,r,id,jd);
return;
}
int qry(int i,int x,int id)
{
int ans=inf;
if(tre[i].st.size())
{
set<int>::iterator it=tre[i].st.lower_bound(id);
for(;it!=tre[i].st.end();++it)if(jud(pot[id],pot[*it])){ans=*it;break;}
}
if(tre[i].l==tre[i].r) return ans;
int mid=(tre[i].l+tre[i].r)>>1;
if(x<=mid) ans=min_(qry(i<<1,x,id),ans);
else ans=min_(qry(i<<1|1,x,id),ans);
return ans;
}
void get_ans(int x)
{
vis[x]=1;
for(int v : vct[x]) get_ans(v),f[x]+=f[v];
f[x]=max_(f[x],pot[x].w);
return;
}
signed main()
{
n=read();
for(int x,y,r,w,i=1;i<=n;++i)x=read(),y=read(),r=read(),w=read(),pot[i]=(pot_){x-r,x+r,y-r,y+r,x,y,r,w};
for(int i=1;i<=n;++i) lsh[++num]=pot[i].xl,lsh[++num]=pot[i].xr;
sort(lsh+1,lsh+num+1);
int k=unique(lsh+1,lsh+num+1)-lsh;
for(int i=1;i<=n;++i)
{
pot[i].xl=lower_bound(lsh+1,lsh+k,pot[i].xl)-lsh;
pot[i].xr=lower_bound(lsh+1,lsh+k,pot[i].xr)-lsh;
}
num=0;for(int i=1;i<=n;++i) lsh[++num]=pot[i].yd,lsh[++num]=pot[i].yp;
sort(lsh+1,lsh+num+1);
k=unique(lsh+1,lsh+num+1)-lsh;
for(int i=1;i<=n;++i)
{
pot[i].yd=lower_bound(lsh+1,lsh+k,pot[i].yd)-lsh;
pot[i].yp=lower_bound(lsh+1,lsh+k,pot[i].yp)-lsh;
}
sort(pot+1,pot+n+1,cmp);
for(int i=1;i<=n;++i) vi[pot[i].xl].push_back(i),vo[pot[i].xr].push_back(i);
build(1,1,2*n);
for(int fa,i=1;i<=2*n;++i)
{
for(int x : vo[i]) insert(1,pot[x].yd,pot[x].yp,x,0);
for(int x : vi[i])
{
fa=qry(1,pot[x].yd,x);
if(fa!=inf) vct[fa].push_back(x);
insert(1,pot[x].yd,pot[x].yp,x,1);
}
}
int ans=0;
for(int i=n;i;--i)if(!vis[i])get_ans(i),ans+=f[i];
cout<<ans<<endl;
return 0;
}
T2
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define il inline
const int N=2e5+11;
const int mod=1e9+7;
struct vct_{signed x,mi;}sta[N][20];
struct tree{signed lc,rc;int val;}tre[8409110];
bool fp[N];
signed q,n,k,a,b,p;
signed root[N],tot;
signed pr[N],num,top[N];
int c[N],d[N];
vector<vct_> vct[N];
int fm(int x,int y){int ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}
il int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
void pre()
{
fp[0]=fp[1]=1;
for(int i=2;i<N;++i)
{
if(!fp[i]) pr[++num]=i,vct[i].push_back({i,1});
for(int tmp,j=1;j<=num&&pr[j]*i<N;++j)
{
fp[tmp=pr[j]*i]=1;
vct[tmp]=vct[i];
if(i%pr[j]==0){++vct[tmp][vct[tmp].size()-1].mi;break;}
else vct[tmp].push_back({pr[j],1});
}
}
return;
}
void ins(signed &i,signed j,int l,int r,int x,int val)
{
i=++tot,tre[i]=tre[j];
if(!tre[i].val) tre[i].val=1;
tre[i].val=tre[i].val*val%mod;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) ins(tre[i].lc,tre[j].lc,l,mid,x,val);
else ins(tre[i].rc,tre[j].rc,mid+1,r,x,val);
return;
}
int qry(signed i,int l,int r,int L,int R)
{
if(!i) return 1;
if(l>=L&&r<=R) return tre[i].val;
int mid=(l+r)>>1;
int val=1;
if(L<=mid) val=qry(tre[i].lc,l,mid,L,R);
if(R>mid) val=val*qry(tre[i].rc,mid+1,r,L,R)%mod;
return val;
}
signed main()
{
pre();
q=read();
n=read(),k=read();
a=read(),b=read(),p=read();
for(int i=2;i<=q;++i) c[i]=read();
for(int i=2;i<=q;++i) d[i]=read();
ins(root[1],root[0],1,1e5,1,1);
for(int mi,pri,mis,loc,now,i=2;i<=1e5;++i)
{
root[i]=root[i-1];
ins(root[i],root[i],1,1e5,i,i);
for(vct_ x : vct[i])
{
now=top[pri=x.x],mi=x.mi;
while(now>0&&(mis=sta[pri][now].mi)<=mi)
{
loc=sta[pri][now].x;
ins(root[i],root[i],1,1e5,loc,fm(fm(x.x,mis),mod-2));
mi-=mis,--now;
}
if(now){if(mi) ins(root[i],root[i],1,1e5,sta[pri][now].x,fm(fm(x.x,mi),mod-2)),sta[pri][now].mi-=mi;}
sta[pri][++now]={i,x.mi};
top[pri]=now;
}
}
int ans=qry(root[n],1,1e5,n-k+1,n);
printf("%lld\n",ans);
for(int i=2;i<=q;++i)
{
n=(a*ans+c[i])%p+1;
k=(b*ans+d[i])%n+1;
printf("%lld\n",ans=qry(root[n],1,1e5,n-k+1,n));
}
return 0;
}