Loading

noip模拟24

A.matrix

简单的状压搜索,记忆化优化..

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll int
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

ll n,m;
ll g[15][15],c[15][15];
ll f[15][(1<<10)+50][(1<<10)+50];

ll Work(ll now,ll dad,ll lst) // 当前是第 now 层,父亲的状态为 dad,父亲选的为 lst
{
	if(now==n+1)
	{
		for(re i=1;i<=m;i++)
		{
			if(((dad>>(i-1))&1)==0) return 1e9;
		}
		return 0;
	}
	if(f[now][dad][lst]) return f[now][dad][lst];
	ll nxt=0,sta=0,cost; 
	for(re i=1;i<=m;i++)
	{
		if((lst>>(i-1))&1) sta|=(1<<(i-1));
		if(g[now][i]) sta|=(1<<(i-1));
		if(((dad>>(i-1))&1)==0) nxt|=(1<<(i-1));
	}
	f[now][dad][lst]=1e9;
	ll temp;
	for(re i=0;i<=(1<<m)-1;i++)
	{
		cost=0; temp=sta;
		if((i|nxt)!=i) continue;
		for(re j=1;j<=m;j++)
		{
			if((i>>j)&1) temp|=(1<<(j-1));
			if((i>>(j-1))&1) temp|=(1<<(j-1));
			if(j>=2) if((i>>(j-2))&1) temp|=(1<<(j-1));
			if((i>>(j-1))&1) cost+=c[now][j];
			if(cost>=f[now][dad][lst]) break;
		}
		if(cost>=f[now][dad][lst]) continue;
		f[now][dad][lst]=min(f[now][dad][lst],cost+Work(now+1,temp,i));
	}
	return f[now][dad][lst];
}
signed main()
{
	n=read(); m=read();
	char s[20];
	for(re i=1;i<=n;i++)
	{	
		scanf("%s",s+1);
		for(re j=1;j<=m;j++)
		{
			g[i][j]=s[j]-'0';
		}
	}
	for(re i=1;i<=n;i++)
	{
		for(re j=1;j<=m;j++)
		{
			c[i][j]=read();
		}
	}
	ll sta,cost,ans=1e9;
	for(re i=0;i<=(1<<m)-1;i++)
	{
		cost=0; sta=0;
		for(re j=1;j<=m;j++)
		{
			if(g[1][j]) sta|=(1<<(j-1));
			if((i>>j)&1) sta|=(1<<(j-1));
			if((i>>(j-1))&1) sta|=(1<<(j-1));
			if(j>=2) if((i>>(j-2))&1) sta|=(1<<(j-1));
			if((i>>(j-1))&1) cost+=c[1][j];
			if(cost>=ans) break;
		}
		if(cost>=ans) continue;
		ans=min(ans,Work(2,sta,i)+cost);
	}
	write(ans);
	return 0;
}		

B.block

第一问和第二问关系不大..
第一问:
考虑插入的方案数即可..
第二问:
考虑线段树维护.
首先保证输出为合法答案,所以当\(key\)存在\(1\),优先考虑其的安置;\(key\)中不含\(1\)时,考虑字典序最小.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

const ll N=6e5+50;
const ll mod=1e9+7;	

ll m,n,ans=1,cnt,tt;
ll pos[N],lsh[N];
struct I { ll val,key; } p[N];
struct II { ll key,posi; } ;
struct III { ll l,r,lazy; II k0,k2; } tr[N*8];
bool comp1(I i,I j) { return i.val==j.val ? i.key<j.key : i.val>j.val; } 
bool comp2(I i,I j) { return i.val==j.val ? i.key<j.key : i.val<j.val; }
inline void Work_One()
{
	sort(p+1,p+1+n,comp1);
	ll lst=0;
	for(ll i=1;i<=n;i++)
	{
		if(p[i].val!=p[i-1].val) 
		{
			ans=(ans*min(i,p[i].key))%mod;
			lst=1;
		}
		else
		{
			ans=(ans*min(i,p[i].key+lst))%mod;
			lst++;
		}
	}
	write(ans); return ;
}
void pushup(ll x)
{
	
	if(tr[x<<1].k0.key<=tr[x<<1|1].k0.key) tr[x].k0=tr[x<<1].k0;
	else tr[x].k0=tr[x<<1|1].k0;
	if(tr[x<<1].k2.key<=tr[x<<1|1].k2.key) tr[x].k2=tr[x<<1].k2;
	else tr[x].k2=tr[x<<1|1].k2;
//	if(tr[x].k0.key==1) cout<<tr[x].k0.key<<" "<<tr[x].l<<" "<<tr[x].r<<" "<<tr[x<<1].k0.key<<" "<<tr[x<<1|1].k0.key<<endl;
	return ;
}
void spread(ll x)
{
	if(tr[x].lazy!=0)
	{
		tr[x<<1].lazy+=tr[x].lazy;
		tr[x<<1|1].lazy+=tr[x].lazy;
		tr[x<<1].k2.key+=tr[x].lazy;
		tr[x<<1|1].k2.key+=tr[x].lazy;
		tr[x].lazy=0;
	}
	return ;
}
void update(ll x,ll ql,ll qr,ll val)
{
	if(ql>qr or qr<=0) return ;
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
		tr[x].k2.key+=val;
		tr[x].lazy+=val;
		if(val==1e10) tr[x].k0.key=tr[x].k2.key=1e10;
		return ;
	}
	spread(x);
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(ql<=mid) update(x<<1,ql,qr,val);
	if(qr>=mid+1) update(x<<1|1,ql,qr,val);
	pushup(x); return ;
}
void build(ll x,ll l,ll r)
{
	tr[x].l=l,tr[x].r=r;
	if(tr[x].l==tr[x].r)
	{
		tr[x].k0.key=tr[x].k2.key=p[l].key;
		tr[x].k0.posi=tr[x].k2.posi=l;
		return ;
	}
	ll mid=(l+r)>>1;
	build(x<<1,l,mid); build(x<<1|1,mid+1,r);
	pushup(x);
}
II query(ll x,ll ql,ll qr)
{
	if(ql>qr) return (II){0,0};
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
		return tr[x].k0;
	}
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(ql<=mid and qr>=mid+1)
	{
		II temp1=query(x<<1,ql,qr);
		II temp2=query(x<<1|1,ql,qr);
		if(temp1.key<=temp2.key) return temp1;
		else return temp2;
	}
	else if(ql<=mid)
	{
		return query(x<<1,ql,qr);
	}
	else if(qr>=mid+1)
	{
		return query(x<<1|1,ql,qr);
	}
}
inline void Work_Two()
{
	sort(p+1,p+1+n,comp2);
	for(re i=1;i<=n;i++) lsh[i]=p[i].val;
	sort(lsh+1,lsh+1+n);
	cnt=unique(lsh+1,lsh+1+n)-lsh-1;
	for(re i=1;i<=n;i++) p[i].val=lb(lsh+1,lsh+1+cnt,p[i].val)-lsh;
	for(re i=1;i<=n;i++) if(p[i].val!=p[i-1].val) pos[p[i].val]=i;
	build(1,1,n);
	for(re i=1;i<=n;i++)
	{
		if(tr[1].k2.key==1)
		{
			II temp=query(1,1,tr[1].k2.posi);
			printf("%lld %lld\n",temp.key,lsh[p[temp.posi].val]);
			update(1,temp.posi,temp.posi,1e10);
			update(1,1,pos[p[temp.posi].val]-1,-1);	
		}
		else
		{
			ll temp=p[tr[1].k0.posi].val;
			printf("%lld %lld\n",tr[1].k0.key,lsh[temp]);
			update(1,tr[1].k0.posi,tr[1].k0.posi,1e10);
			update(1,1,pos[temp]-1,-1);
		}
	}
	return ;
}
signed main()
{
//	File(0.in,out);
	n=read();
	for(re i=1;i<=n;i++) p[i].key=read(),p[i].val=read();
	Work_One(); Work_Two();
	return 0;
}

C.graph

如果一个点能位于 \(1\) ~ \(n\) 的最短路上,那么 \(dis_{1,i}+dis_{i,n}==dis_{1,n}\).
所以考虑如何找到一个 \(x\) ,能够满足上述条件.
暴力的思想就是枚举 \(x\) 的所有值,考虑如何优化.
\(dis_{i,j}\) 为到达点 \(i\),经过了 \(j\)\(x\) 边的最短距离.
发现 \(x\) 的值域位于某一个区间内时,效果是等价的.
由于 \(x\) 的值越大,越不可能经过 \(x\) 边,所以可以对于每一个 \(i\) 计算出以它作为最小值的 \(x\) 取值区间.
在这个取值区间中随便取一个值赋给 \(x\),然后跑两个最短路.
对于每个节点判断是否有可能在最短路上即可.
这样就可以统计所有点,简单反证就可以证明其合理性.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=1021,M=2021;
const ll inf=1e12;

int ans[N];
ll m,n,ts,sum;
ll head[N],v[N];
ll d[N][2],dis[N][M],vis[N][M];
struct I { ll u,v,w,nxt; } e[M<<1];
struct II {
	ll u,xs,w;
	II(){} II(ll i,ll j,ll k){ u=i,xs=j,w=k; }
	bool operator <(const II &x)const{
		return x.w<w;
	}
	
};
struct III {
	ll u,w;	
	III(){} III(ll i,ll j){ u=i,w=j; }
	bool operator <(const III &x)const{
		return x.w<w;
	}
};
priority_queue<II> que; priority_queue<III> Q;
inline void add(ll u,ll v,ll w){
	e[++ts].u=u,e[ts].v=v,e[ts].w=w,e[ts].nxt=head[u],
	head[u]=ts;
}
inline void Dijk(){
	Fill(dis,0x3f); while(que.size()) que.pop();
	dis[1][0]=0,que.push(II(1,0,0)); ll u,xs; 
	while(que.size()){
		u=que.top().u,xs=que.top().xs,que.pop();
		if(vis[u][xs]) continue; vis[u][xs]=1;
		for(re i=head[u];i;i=e[i].nxt){
			if(e[i].w==-1){
				if(xs<sum and dis[e[i].v][xs+1]>dis[u][xs]){
					dis[e[i].v][xs+1]=dis[u][xs];
					que.push(II(e[i].v,xs+1,dis[e[i].v][xs+1]));
				}
			}
			else{
				if(dis[e[i].v][xs]>dis[u][xs]+e[i].w){
					dis[e[i].v][xs]=dis[u][xs]+e[i].w;
					que.push(II(e[i].v,xs,dis[e[i].v][xs]));
				}
			}
		}
	}
}
inline void dijk(ll z,ll x){
	Fill(v,0); while(Q.size()) Q.pop();
	if(z) d[1][1]=0,Q.push(III(1,0));
	else d[n][0]=0,Q.push(III(n,0));
	ll u;
	while(Q.size()){
		u=Q.top().u,Q.pop();
		if(v[u]) continue; v[u]=1;
		for(re i=head[u];i;i=e[i].nxt){
			if(e[i].w==-1){
				if(d[e[i].v][z]>d[u][z]+x){
					d[e[i].v][z]=d[u][z]+x;
					Q.push(III(e[i].v,d[e[i].v][z]));
				}
			}
			else{
				if(d[e[i].v][z]>d[u][z]+e[i].w){
					d[e[i].v][z]=d[u][z]+e[i].w;
					Q.push(III(e[i].v,d[e[i].v][z]));
				}
			}
		}
	}
}
signed main(){
	n=read(),m=read(); ll u,v,w,l,r;
	for(re i=1;i<=m;i++) 
		u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w),sum+=(w==-1);
	Dijk();
//	for(re i=0;i<=sum;i++){
//		for(re j=1;j<=n;j++)
//			cout<<dis[j][i]<<' ';
//		cout<<endl;
//	}
	for(re i=0;i<=sum;i++){
		l=0,r=inf;
		for(re j=0;j<i;j++) r=min(r,(dis[n][j]-dis[n][i])/(i-j));
		for(re j=i+1;j<=sum;j++) l=max(l,(ll)ceil((lf)(dis[n][i]-dis[n][j])/(j-i)));
		if(l>r) continue; Fill(d,0x3f),dijk(1,l),dijk(0,l);
//		cout<<"L:"<<l<<" R:"<<r<<endl;
//		for(re j=1;j<=n;j++) cout<<d[j][0]<<" "<<d[j][1]<<endl;
//		cout<<endl;
		for(re j=1;j<=n;j++) if(d[j][1]+d[j][0]==d[n][1]) ans[j]=1;
	}
	for(re i=1;i<=n;i++) printf("%d",ans[i]);
	exit(0);
}
posted @ 2021-08-05 20:02  AaMuXiiiiii  阅读(31)  评论(0编辑  收藏  举报