题解:
期望递推
\(code\):
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<cmath>
#define ll long long
#define ld double
#define eps 1e-7
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):x=tt^'0';
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
}
const int maxn=21;
int n,w[maxn],tot;
ll ans;
ld f[1<<maxn],p[maxn];
int lowbit(int x){return x&-x;}
bool same(ld a,ld b){return fabs(a-b)<=eps;}
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%lf%d",&p[i],&x);
if(!same(p[i],0.0)) ans+=x,tot|=(1<<i-1);
}
for(int s=1;s<=tot;s++)
{
ld t1=0.0,t2=0.0;
for(int i=0;i<n;i++)
if(s>>i&1)
{
t1+=p[i+1];
t2+=p[i+1]*f[s^(1<<i)];
}
if(!same(t1,0))
f[s]=(t2+1.0)/t1;
}
printf("%lld\n%.3lf",ans,f[tot]);
}
题解:
\(tarjan\)缩点贪心找所有点入边最短;
\(code:\)
找不到了qwq
题解:
线段树维护,考虑每次移动的影响
\(code:\)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<ctype.h>
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
while(!isdigit(tt=gc()));x=tt^'0';
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
}
ll n,mi[2400001],sum[2400001],lazy[2400001],M=1;
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r>>1)
void modify(int p,int l,int r,int x,int y,ll d)
{
if(l==x&&r==y)
{
mi[p]+=d;
lazy[p]+=d;
return;
}
if(x<=mid) modify(ls,l,mid,x,min(y,mid),d);
if( y>mid) modify(rs,mid+1,r,max(x,mid+1),y,d);
if(mi[ls]==mi[rs])
mi[p]=mi[ls]+lazy[p],sum[p]=sum[ls]+sum[rs];
else
{
int t=mi[ls]<mi[rs]?ls:rs;
mi[p]=mi[t]+lazy[p];
sum[p]=sum[t];
}
}
ll ans=0,dep;
void query(int p,int l,int r,int x,int y)
{
if(l==x&&r==y)
{
if(mi[p]+dep==0)
ans+=sum[p];
return;
}
dep+=lazy[p];
if(x<=mid) query(ls,l,mid,x,min(y,mid));
if( y>mid) query(rs,mid+1,r,max(x,mid+1),y);
}
void maketree(int p,int l,int r)
{
if(l==r)
{
mi[p]=0;
sum[p]=1;
return;
}
maketree(ls,l,mid);
maketree(rs,mid+1,r);
mi[p]=0;
sum[p]=r-l+1;
}
int la,lb,posa[600001],posb[600001],a[600001],b[600001],s[600001];
int main()
{
read(n);
for(int i=1,x;i<=n;i++)
read(x),read(s[x]);
posa[0]=n+1;posb[0]=n+1;
maketree(1,1,n);
for(int i=n;i;i--)
{
while(la&&a[la]<=s[i])
{
modify(1,1,n,posa[la],posa[la-1]-1,s[i]-a[la]);
--la;
}
while(lb&&b[lb]>=s[i])
{
modify(1,1,n,posb[lb],posb[lb-1]-1,b[lb]-s[i]);
--lb;
}
a[++la]=s[i];posa[la]=i;
b[++lb]=s[i];posb[lb]=i;
dep=0;
query(1,1,n,i,n);
modify(1,1,n,i,n,-1);
}
printf("%lld",ans);
}
题解:
线段树优化建图,\(tarjan\)缩点,然而可以\(O(N)\)扫过去记录左右最大;
\(code:\)
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<vector>
#define ll long long
using namespace std;
const int mod=1e9+7;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt^'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
ll n,x[500005],R[500005],l[500005],r[500005],ans;
main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld%lld",&x[i],&R[i]),l[i]=r[i]=i;
for(int i=1;i<=n;i++)
while(l[i]>1&&x[i]-x[l[i]-1]<=R[i])
l[i]=l[l[i]-1],R[i]=max(R[i],R[l[i]]-(x[i]-x[l[i]]));
for(int i=n;i>=1;i--)
while(r[i]<n&&x[r[i]+1]-x[i]<=R[i])
r[i]=r[r[i]+1],l[i]=min(l[i],l[r[i]]);
for(int i=1;i<=n;i++) ans=(ans+i*(r[i]-l[i]+1))%1000000007;
printf("%lld",ans);
}
题解:
神仙题,期望递推
\(code:\)
待补
题解:
状压,\(O(N^2)\)枚举两两关系,\(g[S]\)数组维护其中元素的合法性,状态转移:\(F[S]=min\{F[S']+1\}(g[S \bigoplus S']==1)\)
\(code:\)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n;
int a[20],f[1<<20],cnt[1<<20];
bool g[1<<20],w[20][20];
int gcd(int a,int b)
{
if(!b) return a;
return gcd(b,a%b);
}
int lowbit(int x)
{
return x&-x;
}
int main()
{
scanf("%d",&n);
memset(f,30,sizeof(f));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),cnt[1<<i-1]=i;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
w[i][j]=w[j][i]=gcd(a[i],a[j])==1;
for(int i=1;i<1<<n;i++)
{
if((i^lowbit(i)) ==0){g[i]=1;continue;}
bool flag=0;
int s=i^lowbit(i);
if(!g[s]) continue;
for(int j=1;j<=n;j++)
if(s>>(j-1)&1) if(!w[cnt[lowbit(i)]][j])
{flag=1;break;}
if(!flag) g[i]=1;
}
f[0]=0;
// for(int i=1;i<=10;i++)printf("%d ",g[i]);
for(int i=1;i<1<<n;i++)
for(int s=(i-1)&i;;s=i&(s-1))
{
if(g[i^s]) f[i]=min(f[i],f[s]+1);
if(!s) break;
}
printf("%d",f[(1<<n)-1]);
}