返回顶部

【比赛】高一下二调2

下载题解
image
其实是一道水题,但容易想偏,如以为是逆序对

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6;
int n,a[N+5],b[N+5],ans;
int main()
{
	freopen("seat.in","r",stdin);
	freopen("seat.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[a[i]]=i;
	}
	for(int i=1;i<=n;i++)
	{
		if(a[i]!=i)
		{
			int pos=b[i];
			swap(a[i],a[pos]);
			b[a[i]]=a[i];
			b[a[pos]]=pos;
			ans++;
		}
	}
	cout<<ans;
	return 0;
}
/*
8
5 4 2 3 6 8 7 1
*/

image
区间DP,也可以用记忆化搜索

区间DP

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6,mod=1e9;
ll f[305][305];
string s;ll n;
int main()
{
//	freopen("school.in","r",stdin);
//	freopen("school.out","w",stdout);
	cin>>s;
	s.insert(s.begin(),'*');//相当于s从一开始输入
	n=s.size()-1;
//	cout<<n;
	for(int i=0;i<=n;i++)f[i][i]=1;
	for(int len=3;len<=n;len++)
	{
		for(int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;
			
			if(s[l]==s[r])
			{
				f[l][r]=f[l+1][r-1];
				for(int k=l+2;k<=r-2;k++)
				{
					if(s[l]==s[k])//不知道为什么可加可不加
						f[l][r]=(f[l][r]+f[l+1][k-1]*f[k][r])%mod;
//					cout<<l<<" "<<r<<" "<<f[l][r]<<endl;
				}
			}
			else 
			{
				f[l][r]=0;//不成立
			}
		}
	}
	cout<<f[1][n];
	return 0;
}
/*
BBAAABAAAAABABBBBBB
ABAAABA

ABABABA
ABCDCA
ABCDEFGHIJKLMNOPQRSTUVWXY/ABCDEFGHIJKLMNOPQRSTUVWXY/Z/YXWVUTSRQPONMLKJIHGFEDCBA/YXWVUTSRQPONMLKJIHGFEDCBA
	A
*/
点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6,mod=1e9;
ll f[305][305];
string s;ll n;
ll dp(int l,int r)
{
//	cout<<l<<" "<<r<<endl;
	if(l>r)return 0;
	if(l==r)return 1;
	if(f[l][r]!=-1)return f[l][r];
	f[l][r]=0;
	for(int i=l+2;i<=r;i++)
	{
		if(s[l]==s[r])f[l][r]=(f[l][r]+(ll)dp(l+1,i-1)*dp(i,r)%mod)%mod;
//		cout<<l<<" "<<r<<" "<<f[l][r]<<endl;
	}
	return f[l][r];
}
int main()
{
	freopen("school.in","r",stdin);
	freopen("school.out","w",stdout);
	memset(f,-1,sizeof(f));
	cin>>s;
	n=s.size();
	int zh=0;
//	cout<<n;
	dp(0,n-1);
	cout<<f[0][n-1];
	return 0;
}
/*
BBAAABAAAAABABBBBBB
ABAAABA

ABABABA
ABCDCA
ABCDEFGHIJKLMNOPQRSTUVWXY/ABCDEFGHIJKLMNOPQRSTUVWXY/Z/YXWVUTSRQPONMLKJIHGFEDCBA/YXWVUTSRQPONMLKJIHGFEDCBA
	A
*/

image
类似糖果,差分约束
一些很容易遗漏的点,如图不一定联通,因为是有向的,所以必须建一个超级源点,但因为题目中说最少的舱室放置1单位的药炸
所以为add(0,i,1)而不是权值为0
还有,差分约束,求最小值,跑最长路,关系式为大于等于关系\(x_i-x_j>=c\),最后答案并不是dis[n],\(dis[i]\)表示就是单独i点权值,所以答案是1~n的和
注意判断无解情况
记得开LONGLONG

SPFA会T
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5,mod=1e9;
ll cnt,n,m,head[N+5],dis[N+5],in[N+5];bool vis[N+5];
struct e
{
	ll from,to,next,w;
}edge[N*2+5];
void add(int u,int v,int w)
{
	edge[++cnt].from=u;
	edge[cnt].to=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt;
}
bool spfa(int st)
{
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
	{
		dis[i]=0;
		in[i]=0;
	}
	dis[st]=0;vis[st]=1;
	queue <int> q;
	q.push(st);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		vis[u]=0;
		in[u]++;
//		cout<<to<<" "<<in[to]<<endl;
		if(in[u]>n)
		{
			return 0;
		}
		for(int i=head[u];i>=0;i=edge[i].next)
		{
			int to=edge[i].to;
			if(dis[to]<dis[u]+edge[i].w)
			{
				dis[to]=dis[u]+edge[i].w;
//				cout<<to<<" "<<dis[to]<<endl;
				if(!vis[to])
				{
					q.push(to);vis[to]=1;
				}
			}
		}
	}
	return 1;
}
int main()
{
//	freopen("c.in","r",stdin);
	freopen("bomb.in","r",stdin);
	freopen("bomb.out","w",stdout);
	memset(head,-1,sizeof(head));
	scanf("%lld%lld",&n,&m);//min
	ll t,a,b;
	for(int i=1;i<=n;i++)add(0,i,1);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&t,&a,&b);
		if(t==1)
		{
			add(a,b,0);add(b,a,0);
		}else if(t==2)
		{
			add(a,b,1);//a<b b-a>=1
			if(a==b)
			{
				cout<<-1<<endl;
				return 0;
			}
		}else if(t==3)
		{
			add(b,a,0);//a>=b
		}else if(t==4)
		{
			add(b,a,1);//a>b
			if(a==b)
			{
				cout<<-1<<endl;
				return 0;
			}
		}else if(t==5)
		{
			add(a,b,0);//a<=b
		}	
	}
	if(!spfa(0))
	{
		cout<<-1<<endl;
		return 0;	
	}
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=dis[i];
	}
	cout<<ans;
	return 0;
}
/*
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1

4 4
1 3 4
1 1 2
1 2 3
1 4 1
*/
Tarjan+拓扑
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5,mod=1e9;
ll cnt,n,m,head[N+5],head2[N+5],in[N+5],cnt2;bool vis[N+5];
struct e
{
	ll from,to,next,w;
}edge[N*3+5],e2[N*3+5];
void add(int u,int v,int w)
{
	edge[++cnt].from=u;
	edge[cnt].to=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt;
}
void add2(int u,int v,int w)
{
	e2[++cnt2].from=u;
	e2[cnt2].to=v;
	e2[cnt2].w=w;
	e2[cnt2].next=head2[u];
	head2[u]=cnt2;
}
int dfn[N+5],low[N+5],dfscnt;
stack<int>stk;
int ge,belong[N+5],size[N+5];
void tarjan(int now)
{
	dfn[now]=low[now]=++dfscnt;
	stk.push(now);
	vis[now]=1;
	for(int i=head[now];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(!dfn[to])
		{
			tarjan(to);
			low[now]=min(low[now],low[to]);
		}else if(vis[to])
		{
			low[now]=min(low[now],dfn[to]);
		}
	}
	if(low[now]==dfn[now])
	{
		int y;
		ge++;
		do
		{
			y=stk.top();
			stk.pop();
			belong[y]=ge;
			size[ge]++;
			vis[y]=0;
		}while(y!=now);
	}
}
ll ans=0,dp[N+5];
void topsort()
{
//	memset(dp,0x3f,sizeof(dp));
	queue <int> q;
	for(int i=1;i<=ge;i++)
		if(!in[i])q.push(i);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int j=head2[u];j;j=e2[j].next)
		{
			int to=e2[j].to;
			in[to]--;dp[to]=max(dp[to],dp[u]+e2[j].w);
//			cout<<dp[to]<<endl;
			if(!in[to])
			{
				ans+=dp[to]*size[to];
				q.push(to);
//				cout<<to<<" "<<dp[to]<<" "<<size[to]<<endl;
			}
		}		
	}
	
	
}
int main()
{
//	freopen("c.in","r",stdin);
	freopen("bomb.in","r",stdin);
	freopen("bomb.out","w",stdout);
//	memset(head,-1,sizeof(head));
	scanf("%lld%lld",&n,&m);//min
	ll t,a,b;
	for(int i=1;i<=n;i++)add(0,i,1);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&t,&a,&b);
		if(t==1)
		{
			add(a,b,0);add(b,a,0);
		}else if(t==2)
		{
			add(a,b,1);//a<b b-a>=1
			if(a==b)
			{
				cout<<-1<<endl;
				return 0;
			}
		}else if(t==3)
		{
			add(b,a,0);//a>=b
		}else if(t==4)
		{
			add(b,a,1);//a>b
			if(a==b)
			{
				cout<<-1<<endl;
				return 0;
			}
		}else if(t==5)
		{
			add(a,b,0);//a<=b
		}	
	}
	for(int i=0;i<=n;i++)
	{
		if(!dfn[i])
		{
			tarjan(i);
		}
	}
	for(int i=1;i<=cnt;i++)
	{
		int from=edge[i].from,to=edge[i].to;
		if(belong[from]!=belong[to])
		{
//			cout<<belong[from]<<" "<<belong[to]<<endl;
			add2(belong[from],belong[to],edge[i].w);
			in[belong[to]]++;
		}else if(belong[from]==belong[to]&&edge[i].w==1)
		{
			cout<<-1<<endl;
			return 0;			
		}
	}
	topsort();
	cout<<ans;
	return 0;
}
/*
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1

4 4
1 3 4
1 1 2
1 2 3
1 4 1
*/

image
二分能过,记得优先队列栈顶为最大值,别用混变量名
注意判断无解情况

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5,mod=1e9;
ll n,c,f;
struct ac
{
	ll sco,m;
}a[N+5];
bool cmp(ac a,ac b)
{
	return a.sco<b.sco;
}
bool check(ll mid)
{
	int lf=(n-1)/2,lr=lf;
	ll mm=a[mid].m;
	priority_queue <ll,vector<ll>,greater<ll> > l,r;
	for(int i=1;i<=mid-1;i++)
	{
		l.push(a[i].m);
	}
	while(!l.empty()&&lf)
	{
		mm+=l.top();
//		cout<<"**"<<l.top()<<endl;
		l.pop();
		lf--;
	}
	if(mm>f)return 0;
	for(int i=mid+1;i<=c;i++)
	{
		r.push(a[i].m);
	}
	while(!r.empty()&&lr)
	{
		mm+=r.top();
//		cout<<r.top()<<endl;
		r.pop();
		lr--;
	}
//	cout<<mm;
	if(mm<=f)return 1;
	else return 0;	
}
int ans=0;
void fen(ll l,ll r)
{
	while(l<=r)
	{
		ll mid=(l+r)>>1;
		if(check(mid))
		{
			l=mid+1;
			ans=mid;
		}else
		{
			r=mid-1;
		}
	}
	if(!a[ans].sco)
	{
		cout<<-1<<endl;
	}else
		cout<<a[ans].sco<<endl;
	exit(0);
}
int main()
{
//	freopen("d.in","r",stdin);
	freopen("money.in","r",stdin);
	freopen("money.out","w",stdout);
//	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>c>>f;
	for(int i=1;i<=c;i++)
	{
		cin>>a[i].sco>>a[i].m;
	}
	sort(a+1,a+1+c,cmp);
//	fen((n+1)/2,c-(n-1)/2);
//	cout<<a[10].sco<<endl;
	fen((n+1)/2,c-(n-1)/2);
//	for(int i=c-(n-1)/2;i>=(n+1)/2;i--)
//	{
////		if(check(i))
////		{
////			cout<<a[i].sco<<endl;
////			return 0;
//////			break;
////		}
//	}	
	cout<<-1;
	return 0;
}
/*
3 5 70
30 25
50 21
20 20
5 18
35 30


*/
还有一种不用二分的写法,挺快的 就是先按中位数排序,前n/2(向下取整)个和后n/2个一定不可能是中位数,所以分别处理出前后n/2个中位数成绩的前缀和
点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5,mod=1e9;
ll n,c,f;
struct ac
{
	ll sco,m;
}a[N+5];
bool cmp(ac a,ac b)
{
	return a.sco<b.sco;
}
int ans=0;
ll sumf[N+5],sume[N+5];
int main()
{
//	freopen("d.in","r",stdin);ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("money.in","r",stdin);
	freopen("money.out","w",stdout);
	cin>>n>>c>>f;
	for(int i=1;i<=c;i++)
	{
		cin>>a[i].sco>>a[i].m;
	}
	sort(a+1,a+1+c,cmp);
	int st=n/2;ll sum=0;
	priority_queue <ll> l,r;//top is max
	for(int i=1;i<=st;i++)
	{
		sum+=a[i].m;
		l.push(a[i].m);
	}
	for(int i=st+1;i<=c-st;i++)
	{
		sumf[i]=sum;
		l.push(a[i].m);
		sum-=l.top();
		sum+=a[i].m;
		l.pop();
		
	}
	sum=0;
	for(int i=c;i>=c-st+1;i--)
	{
		sum+=a[i].m;
		r.push(a[i].m);
	}
	for(int i=c-st;i>=st+1;i--)
	{
		sume[i]=sum;
		r.push(a[i].m);
		sum-=r.top();
		sum+=a[i].m;
		r.pop();
	}
	ll ans=-1;
	for(int i=st+1;i<=c-st;i++)
	{
////		cout<<sumf[i]<<" "<<sume[i]<<" "<<a[i].m<<endl;
		
		if(sumf[i]+sume[i]+a[i].m<=f)
		{
			ans=max(ans,a[i].sco);
		}
	}
	cout<<ans;
	return 0;
}
/*
3 5 70
30 25
50 21
20 20
5 18
35 30
*/

image
二分,被卡了,不具有单调性死了

posted @ 2024-04-15 15:29  wlesq  阅读(18)  评论(0编辑  收藏  举报