T1 Inverse

1≤n≤500,0≤k≤501\leq n\leq 500,0\leq k\leq 501≤n≤500,0≤k≤50
设f(i,j,k)f(i,j,k)f(i,j,k)表示kkk次操作后Pi<PjP_i<P_jPi<Pj的概率。
考虑暴力O(n4k)O(n^4k)O(n4k)的转移:
- r<ir<ir<i或l>jl>jl>j或i<l≤r<ji<l\leq r<ji<l≤r<j,f(i,j,k−1)→f(i,j,k)f(i,j,k-1)\rightarrow f(i,j,k)f(i,j,k−1)→f(i,j,k)
- l≤i≤r<jl\leq i\leq r<jl≤i≤r<j,f(l+r−i,j,k−1)→f(i,j,k)f(l+r-i,j,k-1)\rightarrow f(i,j,k)f(l+r−i,j,k−1)→f(i,j,k)
- i<l≤j≤ri<l\leq j\leq ri<l≤j≤r,f(i,l+r−j,k−1)→f(i,j,k)f(i,l+r-j,k-1)\rightarrow f(i,j,k)f(i,l+r−j,k−1)→f(i,j,k)
- l≤i<j≤rl\leq i< j\leq rl≤i<j≤r,1−f(l+r−j,l+r−i,k−1)→f(i,j,k)1-f(l+r-j,l+r-i,k-1)\rightarrow f(i,j,k)1−f(l+r−j,l+r−i,k−1)→f(i,j,k)
前缀和的前缀和将复杂度优化到O(n2k)O(n^2k)O(n2k)(为简洁表达,忽略kkk一维):
- 对于第二类l≤i≤r<jl\leq i\leq r<jl≤i≤r<j,贡献为
∑l=1i∑r=ij−1f(l+r−i,j)\ \ \ \ \sum\limits_{l=1}^i\sum\limits_{r=i}^{j-1}f(l+r-i,j) l=1∑ir=i∑j−1f(l+r−i,j)
=∑l=1i∑r=0j−i−1f(l+r,j)=\sum\limits_{l=1}^i\sum\limits_{r=0}^{j-i-1}f(l+r,j)=l=1∑ir=0∑j−i−1f(l+r,j)
设S1(n,j)=∑i=1nf(i,j),S2(n,j)=∑i=1nS1(i,j)S_1(n,j)=\sum\limits_{i=1}^nf(i,j),S_2(n,j)=\sum\limits_{i=1}^nS_1(i,j)S1(n,j)=i=1∑nf(i,j),S2(n,j)=i=1∑nS1(i,j)
则
∑l=1i∑r=0j−i−1f(l+r,j)\ \ \ \ \sum\limits_{l=1}^i\sum\limits_{r=0}^{j-i-1}f(l+r,j) l=1∑ir=0∑j−i−1f(l+r,j)
=∑l=1iS1(l+j−i−1,j)−S1(l−1,j)=\sum\limits_{l=1}^iS_1(l+j-i-1,j)-S_1(l-1,j)=l=1∑iS1(l+j−i−1,j)−S1(l−1,j)
=S2(j−1,j)−S2(j−i−1,j)−S2(i−1,j)=S_2(j-1,j)-S_2(j-i-1,j)-S_2(i-1,j)=S2(j−1,j)−S2(j−i−1,j)−S2(i−1,j) - 对于第三类i<l≤j≤ri<l\leq j\leq ri<l≤j≤r,贡献为
∑l=i+1j∑r=jnf(i,l+r−j)\ \ \ \ \sum\limits_{l=i+1}^j\sum\limits_{r=j}^{n}f(i,l+r-j) l=i+1∑jr=j∑nf(i,l+r−j)
=∑l=i+1j∑r=0n−jf(i,l+r)=\sum\limits_{l=i+1}^j\sum\limits_{r=0}^{n-j}f(i,l+r)=l=i+1∑jr=0∑n−jf(i,l+r)
设S3(i,t)=∑j=tnf(i,j),S4(i,t)=∑j=tnS3(i,j)S_3(i,t)=\sum\limits_{j=t}^nf(i,j),S_4(i,t)=\sum\limits_{j=t}^nS_3(i,j)S3(i,t)=j=t∑nf(i,j),S4(i,t)=j=t∑nS3(i,j)
则
∑l=i+1j∑r=0n−jf(i,l+r)\ \ \ \ \sum\limits_{l=i+1}^j\sum\limits_{r=0}^{n-j}f(i,l+r) l=i+1∑jr=0∑n−jf(i,l+r)
=∑l=i+1jS3(i,l)−S3(i,l+n−j+1)=\sum\limits_{l=i+1}^jS_3(i,l)-S_3(i,l+n-j+1)=l=i+1∑jS3(i,l)−S3(i,l+n−j+1)
=S4(i,i+1)−S4(i,j+1)−S4(i,n+i−j+2)=S_4(i,i+1)-S_4(i,j+1)-S_4(i,n+i-j+2)=S4(i,i+1)−S4(i,j+1)−S4(i,n+i−j+2) - 对于第四类l≤i<j≤rl\leq i<j\leq rl≤i<j≤r,贡献为
i×(n−j+1)−∑l=1i∑r=jnf(l+r−j,l+r−i)i\times(n-j+1)-\sum\limits_{l=1}^i\sum\limits_{r=j}^{n}f(l+r-j,l+r-i)i×(n−j+1)−l=1∑ir=j∑nf(l+r−j,l+r−i)
其中
∑l=1i∑r=jnf(l+r−j,l+r−i)\ \ \ \ \sum\limits_{l=1}^i\sum\limits_{r=j}^{n}f(l+r-j,l+r-i) l=1∑ir=j∑nf(l+r−j,l+r−i)
=∑l=1i∑r=0n−jf(l+r,l+r+j−i)=\sum\limits_{l=1}^i\sum\limits_{r=0}^{n-j}f(l+r,l+r+j-i)=l=1∑ir=0∑n−jf(l+r,l+r+j−i)
设g(i,j)=f(i,i+j)g(i,j)=f(i,i+j)g(i,j)=f(i,i+j)
则
∑l=1i∑r=0n−jf(l+r,l+r+j−i)\ \ \ \ \sum\limits_{l=1}^i\sum\limits_{r=0}^{n-j}f(l+r,l+r+j-i) l=1∑ir=0∑n−jf(l+r,l+r+j−i)
=∑l=1i∑r=0n−jg(l+r,j−i)=\sum\limits_{l=1}^i\sum\limits_{r=0}^{n-j}g(l+r,j-i)=l=1∑ir=0∑n−jg(l+r,j−i)
设S5(n,j)=∑i=1ng(i,j),S6(n,j)=∑i=1nS5(i,j)S_5(n,j)=\sum\limits_{i=1}^{n} g(i,j),S_6(n,j)=\sum\limits_{i=1}^nS_5(i,j)S5(n,j)=i=1∑ng(i,j),S6(n,j)=i=1∑nS5(i,j)
则
∑l=1i∑r=0n−jg(l+r,j−i)\ \ \ \ \sum\limits_{l=1}^i\sum\limits_{r=0}^{n-j}g(l+r,j-i) l=1∑ir=0∑n−jg(l+r,j−i)
=∑l=1iS5(l+n−j,j−i)−S5(l−1,j−i)=\sum\limits_{l=1}^iS_5(l+n-j,j-i)-S_5(l-1,j-i)=l=1∑iS5(l+n−j,j−i)−S5(l−1,j−i)
=S6(n+i−j,j−i)−S6(n−j,j−i)−S6(i−1,j−i)=S_6(n+i-j,j-i)-S_6(n-j,j-i)-S_6(i-1,j-i)=S6(n+i−j,j−i)−S6(n−j,j−i)−S6(i−1,j−i)
如上维护即可。
#include<bits/stdc++.h>
#define rep(i,x,y) for(i=x;i<=y;++i)
#define req(i,x,y) for(i=x;i>=y;--i)
#define gc getchar
using namespace std;
typedef long long ll;
typedef double db;
const int N=505,mod=1e9+7;
int n,m,ini[N],f[N][N],ss[N],nv;
int a[N][N],b[N][N],c[N][N];
ll ans;
inline void ad(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void dc(int &x,int y){x-=y;if(x<0) x+=mod;}
inline int adi(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dci(int x,int y){x-=y;return x<0?x+mod:x;}
char cp,os[100];
template<class T>inline void rd(T &x)
{
cp=gc();x=0;int f=0;
for(;!isdigit(cp);cp=gc()) if(cp=='-') f=1;
for(;isdigit(cp);cp=gc()) x=x*10+(cp^48);
if(f) x=-x;
}
inline int fp(int x,int y)
{
int re=1;
for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) re=(ll)re*x%mod;
return re;
}
int main(){
int i,j,k,v;rd(n);rd(m);
rep(i,1,n) rd(ini[i]),ss[i]=ss[i-1]+i;
rep(i,1,n) rep(j,i+1,n) f[i][j]=(ini[i]>ini[j]);
nv=fp(ss[n],mod-2);
for(;m;--m){
rep(j,2,n){
rep(i,1,j-1) a[i][j]=adi(a[i-1][j],f[i][j]);
rep(i,1,j-1) ad(a[i][j],a[i-1][j]);
}
rep(i,1,n){
req(j,n,i+1) b[i][j]=adi(b[i][j+1],f[i][j]);
req(j,n,i+1) ad(b[i][j],b[i][j+1]);
}
rep(j,0,n){
rep(i,1,n-j) c[i][j]=adi(c[i-1][j],f[i][i+j]);
rep(i,1,n-j) ad(c[i][j],c[i-1][j]);
}
rep(i,1,n)
rep(j,i+1,n){
v=(ll)f[i][j]*(ss[i-1]+ss[j-i-1]+ss[n-j])%mod;
ad(v,dci(a[j-1][j],adi(a[j-i-1][j],a[i-1][j])));
ad(v,dci(b[i][i+1],adi(b[i][j+1],b[i][n+i-j+2])));
dc(v,dci(c[n+i-j][j-i],adi(c[n-j][j-i],c[i-1][j-i])));
ad(v,i*(n-j+1));
f[i][j]=(ll)v*nv%mod;
}
}
rep(i,1,n) rep(j,i+1,n) ans+=f[i][j];
printf("%d",ans%mod);
fclose(stdin);fclose(stdout);
return 0;
}
T2 Subsequence
n≤105,∣Ai∣≤107n\leq 10^5,|A_i|\leq 10^7n≤105,∣Ai∣≤107
设f(i,j)f(i,j)f(i,j)表示前iii个数选了jjj个数的最大权值,则
f(i,j)=max(f(i−1,j),f(i−1,j−1)+j×Ai)f(i,j)=max(f(i-1,j),f(i-1,j-1)+j\times A_i)f(i,j)=max(f(i−1,j),f(i−1,j−1)+j×Ai)
打表/感性/证明发现:对于每一个iii,满足f(i,j)f(i,j)f(i,j)最优的jjj的范围一定是一端以iii的后缀。考虑bstbstbst维护dpdpdp值的差分,即f(i,j)−f(i,j−1)f(i,j)-f(i,j-1)f(i,j)−f(i,j−1)。
每次新加入末端的一个数aia_iai,首先二分找出其在bstbstbst上所处位置,然后将后面所有点打上+ai+a_i+ai标记即可。
#include<bits/stdc++.h>
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
#define F(x) t[x].fa
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,a[N],rt,num,stk[N],top;
ll ans[N];
char cp;
inline void rd(int &x)
{
cp=getchar();x=0;int f=0;
for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=1;
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
if(f) x=-x;
}
struct node{int ch[2],fa,sz;ll g,lzy;}t[N];
inline void pu(int x)
{if(!x) return;t[x].sz=t[lc(x)].sz+t[rc(x)].sz+1;}
inline void dn(int x)
{
if(!t[x].lzy) return;
if(lc(x)){
t[lc(x)].lzy+=t[x].lzy;
t[lc(x)].g+=t[x].lzy;
}
if(rc(x)){
t[rc(x)].lzy+=t[x].lzy;
t[rc(x)].g+=t[x].lzy;
}
t[x].lzy=0LL;
}
void ins(int fr,int &x,int id,int v,int bs)
{
if(!x) {x=id;F(x)=fr;t[x].g=(ll)(bs+1)*v;return;}
dn(x);
if((ll)(bs+t[lc(x)].sz+1)*v>t[x].g) ins(x,lc(x),id,v,bs);
else ins(x,rc(x),id,v,bs+t[lc(x)].sz+1);
pu(x);
}
void dfs(int x)
{
dn(x);
if(lc(x)) dfs(lc(x));
num++;
ans[num]=t[x].g;
if(rc(x)) dfs(rc(x));
}
inline void rot(int x)
{
int y=F(x),z=F(y),dr=(rc(y)==x);
t[y].ch[dr]=t[x].ch[dr^1];
if(t[y].ch[dr]) F(t[y].ch[dr])=y;
F(x)=z;if(z) t[z].ch[rc(z)==y]=x;
F(y)=x;t[x].ch[dr^1]=y;pu(y);
}
inline void splay(int x)
{
int y,z;
for(y=x;y;y=F(y)) stk[++top]=y;
for(;top;--top) dn(stk[top]);
for(;F(x);rot(x)){
y=F(x);z=F(y);
if(z) ((rc(y)==x)^(rc(z)==y))?rot(x):rot(y);
}
rt=x;pu(x);
}
int main(){
int i,j;rd(n);
for(i=1;i<=n;++i) rd(a[i]),t[i].sz=1;
rt=1;t[1].g=a[1];
for(i=2;i<=n;++i){
ins(0,rt,i,a[i],0);splay(i);
if(rc(i)){t[rc(i)].lzy+=a[i];t[rc(i)].g+=a[i];}
}
dfs(rt);
for(i=2;i<=num;++i) ans[i]+=ans[i-1];
for(i=1;i<=num;++i) printf("%lld ",ans[i]);
return 0;
}
T3 Convex

4≤n≤2×106,∣xi∣,∣yi∣≤1094\leq n\leq2\times 10^6,|x_i|,|y_i|\leq 10^94≤n≤2×106,∣xi∣,∣yi∣≤109
两半的面积之差可以转成∣S−2X∣|S-2X|∣S−2X∣,其中SSS为总面积,XXX为其中一半的面积。
枚举对角线,考虑固定对角线的一端,其对踵点前的一段区间均满足2X≤S2X\leq S2X≤S,后一段均满足2X>S2X>S2X>S,拆绝对值后转成了求边叉积(相当于一些以原点为端点的三角形的有向面积)的前缀和。再维护一个端点横纵坐标的前缀和,大力讨论即可。
复杂度O(n)O(n)O(n)(线性求对踵点,代码二分求的对踵点(O(nlogn)O(n\log n)O(nlogn)也可过)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e6+10,mod=1e9+7;
int n,ans,dz[N],pz[N],ss;
ll sum,qz[N];
struct P{
ll x,y;
P(ll x_=0,ll y_=0):x(x_),y(y_){};
P operator -(const P&ky){return P(x-ky.x,y-ky.y);}
P operator +(const P&ky){return P(x+ky.x,y+ky.y);}
}p[N],s[N];
inline ll cg(P a,P b){return a.x*b.y-a.y*b.x;}
inline int fp(int x,int y)
{
int re=1;
for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) re=(ll)re*x%mod;
return re;
}
inline void ad(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void dc(int &x,int y){x-=y;if(x<0) x+=mod;}
inline int adi(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dci(int x,int y){x-=y;return x<0?x+mod:x;}
inline char gc()
{
static char buf[1000005];static int p1=0,p2=0;
if(p1==p2) p1=0,p2=fread(buf,1,1000005,stdin);
if(p1==p2) return EOF;return buf[p1++];
}
char cp,os[100];
template<class T>inline void rd(T &x)
{
cp=gc();x=0;int f=0;
for(;!isdigit(cp);cp=gc()) if(cp=='-') f=1;
for(;isdigit(cp);cp=gc()) x=x*10+(cp^48);
if(f) x=-x;
}
template<class T>inline void ot(T x)
{
if(x<0) putchar('-'),x=-x;
int re=0;
for(;(!re)||x;x/=10) os[++re]='0'+x%10;
for(;re;--re) putchar(os[re]);
}
inline int zlh(ll x){x%=mod;return x<0?x+mod:x;}
inline ll askk(int l,int r){
if(r<=n) return qz[r]-qz[l-1];
return sum-(qz[l-1]-qz[r-n]);
}
inline ll gtarea(int l,int r){return askk(l,r-1)+cg(p[l],p[r]);}
inline void sol(int id)
{
int l=id+2,r=id-2+n,mid,re=id,bs,res,o=0;
for(;l<=r;){
mid=(l+r)>>1;
((gtarea(id,mid))<=(sum>>1))?l=(re=mid)+1:r=mid-1;
}
if(re!=id){
bs=n-3-((re-id-1)<<1);ad(ans,zlh(-(ll)bs*ss));
res=dci(dz[re-1],dz[id]);
ad(res,zlh((ll)(bs-1-id)*dci(pz[re-1],pz[id])));
ad(res,zlh((ll)bs*dci(pz[id],pz[id-1])));
ad(o,res);
res=dci((ll)zlh(p[id].x)*dci(s[re].y,s[id+1].y)%mod,(ll)zlh(p[id].y)*dci(s[re].x,s[id+1].x)%mod);
dc(o,res);
if(re<id-2+n){
bs=id-2+n-re;
res=dci(dz[id-3+n],dz[re-1]);
ad(res,zlh((ll)(-re-bs)*dci(pz[id-3+n],pz[re-1])));
dc(o,res);
res=dci((ll)zlh(p[id].x)*dci(s[id-2+n].y,s[re].y)%mod,(ll)zlh(p[id].y)*dci(s[id-2+n].x,s[re].x)%mod);
ad(o,res);
}
}else{
dc(ans,(ll)(n-3)*ss%mod);
bs=id-2+n;res=dci(dz[bs-1],dz[id]);
ad(res,zlh((ll)(-n+3-id-1)*dci(pz[bs-1],pz[id])));
ad(res,zlh((ll)(-n+3)*dci(pz[id],pz[id-1])));
dc(o,res);
res=dci((ll)zlh(p[id].x)*dci(s[bs].y,s[id+1].y)%mod,(ll)zlh(p[id].y)*dci(s[bs].x,s[id+1].x)%mod);
ad(o,res);
}
ad(ans,adi(o,o));
}
int main(){
int i;ll res;rd(n);qz[0]=0LL;
for(i=1;i<=n;++i) rd(p[i].x),rd(p[i].y);
for(i=2;i<=n;++i) p[i]=p[i]-p[1];p[1]=P(0LL,0LL);
for(i=1;i<=n;++i) p[i+n]=p[i];
for(i=1;i<=n;++i) qz[i]=qz[i-1]+cg(p[i+1],p[i]);
for(i=1;i<n+n;++i){
s[i]=s[i-1]+p[i];s[i].x=zlh(s[i].x);s[i].y=zlh(s[i].y);
pz[i]=adi(pz[i-1],zlh(cg(p[i+1],p[i])));
}
sum=qz[n];ss=pz[n];
for(i=1;i<n+n;++i) dz[i]=adi(dz[i-1],(ll)i*dci(pz[i],pz[i-1])%mod);
for(i=1;i<=n;++i) sol(i);
printf("%d",(ll)ans*fp(2,mod-2)%mod);
fclose(stdin);fclose(stdout);
return 0;
}
小结
T1连dp转移都没想出来,更别说后面的繁琐讨论+求前缀和的前缀和的优化了。
T2比较套路,但还是没有联想到最优决策是一段后缀就上bstbstbst。
T3很傻,但还是码了很久。

这篇博客详细解析了三道竞赛题目:T1涉及概率计算,通过前缀和优化暴力转移;T2是最大权值子序列问题,使用BST维护差分;T3处理几何问题,通过求边叉积的前缀和解决。文章总结了每道题目的难点和解题思路。
521

被折叠的 条评论
为什么被折叠?



