题解:
正解很简单就是新来一个加一个......走一个减一个......而我就比较弱智了,线段树区间修改,维护全局最大值......
\(code\):
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#define ll long long
#define inf 1e9+9
#include<ctype.h>
#include<cstring>
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(x=0,flag=1):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
char pbuf[1<<20],*pp=pbuf;
inline void push(const char c)
{
if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
*pp++=c;
}
template<typename T>
inline void write(T x)
{
static int sta[35];
int top=0;
if(x<0) push('-'),x=-x;
do {
sta[top++]=x%10,x/=10;
} while(x);
while(top) push(sta[--top]+'0');
push('\n');
}
struct node{
int x,y;
};
int n,tot,root;
map<char,node>pos;
map<char,bool>book;
string ss;
int ls[100005<<2],rs[100005<<2],maxx[100005<<2],lazy[100005<<2];
void modify(int &p,int l,int r,int x,int y,int d)
{
if(!p) p=++tot;
if(x<=l&&y>=r)
{
maxx[p]+=d;
lazy[p]+=d;
return;
}
int mid=l+r>>1;
if(x<=mid) modify(ls[p],l,mid,x,y,d);
if(y>mid) modify(rs[p],mid+1,r,x,y,d);
maxx[p]=max(maxx[ls[p]],maxx[rs[p]])+lazy[p];
}
int main()
{
cin>>ss;
n=ss.length();
for(int i=0;i<n;i++)
if(!pos[ss[i]].x) pos[ss[i]].x=i+1;
for(int i=n-1;i>=0;i--)
if(!pos[ss[i]].y) pos[ss[i]].y=i+1;
for(int i=0;i<n;i++)
{
if(book[ss[i]]) continue;
modify(root,1,n,pos[ss[i]].x,pos[ss[i]].y,1);
book[ss[i]]=1;
}
printf("%d",maxx[root]);
// fwrite(pbuf,1,pp-pbuf,stdout);
}
题解:
拓扑排序,裸的期望递推,顺便记下OBlack大佬的叮嘱:"期望一般逆推,概率一般顺推";
\(code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#define ll long long
#define inf 30000000000000000LL
//#define inf 1000
#define ld double
#include<ctype.h>
#include<cstring>
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc() {
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
void read(T &x) {
char tt;
bool flag=0;
while(!isdigit(tt=getchar())&&tt!='-');
tt=='-'?(x=0,flag=1):(x=tt-'0');
while(isdigit(tt=getchar())) x=x*10+tt-'0';
if(flag) x=-x;
}
char pbuf[1<<20],*pp=pbuf;
inline void push(const char c) {
if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
*pp++=c;
}
template<typename T>
inline void write(T x) {
static int sta[35];
int top=0;
if(x<0) push('-'),x=-x;
do {
sta[top++]=x%10,x/=10;
} while(x);
while(top) push(sta[--top]+'0');
push('\n');
}
struct node {
int x;
ld len;
inline node(int a=0,ld b=0.0) {
x=a;
len=b;
}
};
int n,m,p,s,t,deg[100005],v[100005],tot;
queue<int>q;
ld f[2][100005];
vector<node>G[100005];
void mysort() {
f[1][s]=1.0;
for(int i=1; i<=n; i++)
if(!deg[i]) q.push(i);
while(!q.empty()) {
int x=q.front();
q.pop();
for(int i=G[x].size()-1; i>=0; i--) {
int pp=G[x][i].x;
ld len=G[x][i].len;
f[1][pp]+=(ld)f[1][x]*len;
--deg[pp];
if(!deg[pp]) q.push(pp);
}
}
}
ld ans;
inline bool cmp(ld a,ld b) {
return a>b;
}
int main() {
//N,M,P,S,T
scanf("%d%d%d%d%d",&n,&m,&p,&s,&t);
for(int i=1; i<=n; i++) scanf("%d",&v[i]);
for(int i=1; i<=m; i++) {
int x,y;
ld z;
scanf("%d%d%lf",&x,&y,&z);
deg[y]++;
G[x].push_back(node(y,z));
}
mysort();
for(int i=1; i<=n; i++) ans+=v[i]*f[1][i];
for(int i=1; i<=n; i++)
if(i!=s) f[0][++tot]=f[1][i];
sort(f[0]+1,f[0]+1+tot,cmp);
t=min(tot,t);
for(int i=1; i<=t; i++) ans+=(ld)p*f[0][i];
printf("%.3lf",ans);
}
题解:
数位DP+二分,由于\(sum\)即满足的数的个数显然是单调不减的,满足二分性质,二分答案后数位DP验证;
状态与平常的数位DP一样,\(F[len][q1][q2][lim][con][more][zero]\),具体表示见代码注释,随后(不久的将来)将发布一篇数位DP心得;
\(code:\)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1e18
#define ll long long
using namespace std;
ll n,l,r;
ll s[20];
ll f[20][12][12][2][2][2][2];
// i位
// j第前一个数
// k第前两个数
// l限制
// m连续
// n后加一
// zero前导零
ll dfs(ll len,ll q1,ll q2,bool lim,bool con,bool more,bool zero)
{
ll &tmp=f[len][q1][q2][lim][con][more][zero];
if(~tmp) return tmp;
tmp=0;
if(more&&con) return tmp=0;
if(!len) return tmp=1;
ll maxx=(lim)?s[len]:9;
ll minn=(zero)?1:0;
for(ll i=minn;i<=maxx;i++)
{
if(i==3&&q1==3&&q2==2) continue;
bool conn=con,morr=more;
if(i==q1) conn|=1; if(q1-1==i) morr|=1;
if(i==maxx) tmp+=dfs(len-1,i,q1,lim,conn,morr,0);
else tmp+=dfs(len-1,i,q1,0,conn,morr,0);
}
return tmp;
}
ll ok(ll x)
{
ll ans=0;
ll len=0;
memset(f,-1,sizeof(f));
do
{
s[++len]=x%10;
x/=10;
}while(x);
// i位
// j第前一个数
// k第前两个数
// l限制
// m连续
// n后加一
// zero前导零
ans+=dfs(len,11,11,1,0,0,1);
for(ll i=len-1;i>=1;i--)
ans+=dfs(i,11,11,0,0,0,1);
return ans;
}
int main()
{
scanf("%lld",&n);
if(n<=99) printf("%lld",n),exit(0);
l=n,r=inf;
while(l<=r)
{
ll mid=l+r>>1;
if(ok(mid)>=n) r=mid-1;
else l=mid+1;
}
printf("%lld",l);
}