noip模拟74
T1
指针扫左端点,此时mex值随右端点递增
考虑左指针移动,也就是删一个值x,贡献是mex刚开始大于x的位置,到x下一次在序列中出现的位置-1,mex全部覆盖为x
线段树区间修改,区间二分值
T2
必定存在某个位置的1不动
考虑枚举这个位置,然后断环为链,记位置i值为\(a_i\),\(sum_i=\sum_{j=1}^{i}a[i]\),\(sum0_i=\sum_{j=1}^{i}[a_i=0]\)
若此时能够造成贡献,满足\(\forall k\in[1,n],sum_i-1-sum0_i>=0\),因为只有前面的1才能放到后面
贡献就贪心地将最后边的1放到最后的0的位置,因为\(a^2+b^2<=(a+b)^2\)
当然这样可能是\(O(n^2)\)的,因为被卡了
两个剪枝
-
搜索合法位置时,若枚举到\(a_i=1\),直接跳过,因为计算合法性有一个\(sum_i-1\),此时\(a_i=1\)没贡献。事实证明这样的剪枝是非常有效的,TLE的代码加上这句话就900msA了,最慢的点229ms
-
枚举到合法位置直接计算贡献然后return。不会证明,但是加上后就900ms变300msA
T3
剩奇数个数都希望拿到正面,偶数反之
设\(a_i\)表示剩i个球时Alice先手赢的概率,\(b_i\)表示剩i个球时Bob先手赢的概率
若i为奇数,\(a_{i+1}=p* b_i+(1-p)* q* a_i+(1-p)* (1-q) *a_{i+1}\)
化简一下,\(a_{i+1}=\frac{p* b_i+(1-p)* q* a_i}{p+q-p* q}\)
偶数时就是把p换成1-p,q换成1-q
b的方程同理
代码
T1
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+11;
struct tree{
int l,r;
int minn;
int sum;
int lazy;
}tre[4*N];
int n;
int ans;
int ton[N];
int a[N],lsh[N];
int nxt[N],last[N];
inline 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;
}
inline int min_(int x,int y){return x>y?y:x;}
void lsh_()
{
sort(lsh+1,lsh+n+1);
int x=unique(lsh+1,lsh+n+1)-lsh;
for(int i=1;i<=n;i++) a[i]=lower_bound(lsh+1,lsh+x,a[i])-lsh;
return;
}
void build(int i,int l,int r)
{
tre[i].lazy=-1;
tre[i].l=l;
tre[i].r=r;
if(l==r) return;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
return;
}
inline void js(int i){tre[i].sum=(tre[i].r-tre[i].l+1)*tre[i].minn;}
inline void pushdown(int i)
{
if(tre[i].l==tre[i].r) return;
tre[i<<1].lazy=tre[i<<1].minn=tre[i].lazy;
tre[i<<1|1].lazy=tre[i<<1|1].minn=tre[i].lazy;
js(i<<1);js(i<<1|1);
tre[i].lazy=-1;
return;
}
inline void update(int i)
{
tre[i].sum=tre[i<<1].sum+tre[i<<1|1].sum;
tre[i].minn=min_(tre[i<<1].minn,tre[i<<1|1].minn);
return;
}
void insert(int i,int x,int sum)
{
if(tre[i].lazy!=-1) pushdown(i);
if(tre[i].l==tre[i].r){tre[i].minn=tre[i].sum=sum;return;}
int mid=(tre[i].l+tre[i].r)>>1;
if(x<=mid) insert(i<<1,x,sum);
else insert(i<<1|1,x,sum);
update(i);
return;
}
int query(int i,int x)
{
if(tre[i].lazy!=-1) pushdown(i);
if(tre[i].l==tre[i].r)
{
if(tre[i].sum>=x) return tre[i].l;
return n+1;
}
int mid=(tre[i].l+tre[i].r)>>1;
if(tre[i<<1|1].minn<x) return query(i<<1|1,x);
else return min_(query(i<<1,x),tre[i<<1|1].l);
return n+1;
}
void change(int i,int l,int r,int x)
{
if(tre[i].lazy!=-1) pushdown(i);
if(tre[i].l>=l&&tre[i].r<=r)
{
tre[i].minn=x;
tre[i].sum=x*(tre[i].r-tre[i].l+1);
tre[i].lazy=x;
return;
}
int mid=(tre[i].l+tre[i].r)>>1;
if(l<=mid) change(i<<1,l,r,x);
if(r>mid) change(i<<1|1,l,r,x);
update(i);
return;
}
signed main()
{
FILE* x=freopen("mex.in","r",stdin);
x=freopen("mex.out","w",stdout);
n=read();
for(int i=1;i<=n;++i) lsh[i]=a[i]=read();
lsh_();
for(int i=1;i<=n;++i)
{
nxt[last[a[i]]]=i;
last[a[i]]=i;
}
build(1,1,n);
for(int i=1;i<=n;++i) if(!nxt[i]) nxt[i]=n+1;
int r=0;
for(int i=1;i<=n;++i)
{
if(lsh[a[i]]<=n) ton[lsh[a[i]]]++;
while(ton[r]) ++r;
insert(1,i,r);
}
ans+=tre[1].sum;
for(int nw,nx,i=1;i<n;++i)
{
nx=nxt[i]-1;
insert(1,i,0);
nw=query(1,lsh[a[i]]+1);
if(nx>=nw) change(1,nw,nx,lsh[a[i]]);
ans+=tre[1].sum;
}
cout<<ans<<endl;
return 0;
}
T2
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+11;
int n;
int a[N];
int tem[N];
vector<int> vct;
inline 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;
}
inline int min_(int x,int y){return x>y?y:x;};
signed main()
{
FILE* x=freopen("barn.in","r",stdin);
x=freopen("barn.out","w",stdout);
bool jd=1;
n=read();
for(int i=1;i<=n;++i) jd&=((a[i]=a[i+n]=read())==1);
if(jd){cout<<0<<endl;return 0;};
for(int i=1;i<=n;i++)
{
if(a[i]==1) continue;
bool jd=1;
int sum0=0,suma=0;
for(int j=i;j<n+i;++j)
{
if(!a[j]) ++sum0;
else suma+=a[j]-1;
if(suma-sum0<0) {jd=0;break;}
}
if(!jd) continue;
vct.push_back(i);
}
long long ans=1e18;
for(int i=0;i<vct.size();i++)
{
long long sum=0;
int st=vct[i];
memcpy(tem+1,a+st,sizeof(int)*n);
int p1=n;
while(tem[p1]) --p1;
int p2=p1;
while(1)
{
while(p2>=p1||!tem[p2]) --p2;
--tem[p2];
tem[p1]=1;
sum+=1ll*(p1-p2)*(p1-p2);
while(p1>0&&tem[p1]) --p1;
if(p1==0) break;
while(p2>=p1||!tem[p2]) --p2;
}
ans=min_(ans,sum);
}
cout<<ans<<endl;
return 0;
}
T3
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inv=571428574;
const int mod=1e9+7;
struct mat_{
int h,l;
int mat[4][4];
friend mat_ operator*(mat_ a,mat_ b)
{
mat_ c;
memset(&c,0,sizeof(c));
for(int i=1;i<=a.h;++i)
for(int k=1;k<=b.h;++k)
{
if(a.mat[i][k]==0) continue;
for(int j=1;j<=b.l;++j)
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
}
c.h=a.h;
c.l=b.l;
return c;
}
}ans,x1,x2,x;
int p,q,n;
inline 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;
}
int fm(int xx,int y)
{
int as=1;
while(y)
{
if(y&1) as=as*xx%mod;
xx=xx*xx%mod;
y>>=1;
}
return as;
}
void solve()
{
int pq=fm((1+mod-p*q%mod),mod-2);
int pq2=fm((p+q-p*q%mod+mod)%mod,mod-2);
x1.h=x2.l=x1.l=x2.h=2;
x1.mat[1][1]=(mod+1-p)*q%mod*pq2%mod;
x1.mat[2][1]=p*pq2%mod;
x1.mat[1][2]=q*pq2%mod;
x1.mat[2][2]=(1-q+mod)*p%mod*pq2%mod;
x2.mat[1][1]=(1-q+mod)*p%mod*pq%mod;
x2.mat[2][1]=(1-p+mod)*pq%mod;
x2.mat[1][2]=(1-q+mod)*pq%mod;
x2.mat[2][2]=(1-p+mod)*q%mod*pq%mod;
x=x1*x2;
memset(&ans,0,sizeof(ans));
ans.h=2,ans.l=2;
ans.mat[1][1]=1;
ans.mat[2][2]=1;
int y=n/2;
while(y)
{
if(y&1) ans=ans*x;
x=x*x;
y>>=1;
}
return;
}
signed main()
{
FILE* x=freopen("game.in","r",stdin);
x=freopen("game.out","w",stdout);
int t=read();
while(t--)
{
n=read();
p=read()*inv%mod;
q=read()*inv%mod;
solve();
mat_ anss;
memset(&anss,0,sizeof(anss));
anss.h=1,anss.l=2;
anss.mat[1][1]=0;
anss.mat[1][2]=1;
if(n&1) ans=ans*x1;
anss=anss*ans;
cout<<anss.mat[1][1]<<endl;
}
return 0;
}