2018.9.24 练习赛

T1 科学馆翻窗

题解:

正解很简单就是新来一个加一个......走一个减一个......而我就比较弱智了,线段树区间修改,维护全局最大值......

\(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);	
}

T2 死宅与陷阱

题解:

拓扑排序,裸的期望递推,顺便记下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);
}

T3 土拨鼠猎人

题解:

数位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);
}
 
posted @ 2018-09-25 00:24  Katoumegumi  阅读(66)  评论(0编辑  收藏  举报
返回顶部