1,acwing 341.最优贸易;2,cf Almost Equal;
1,最优贸易;
思路:采取dp的思想,枚举分界点,求1到分界点的最小买入价格和分界点到n的最大卖出价格;
注意dijkstra和spfa的区别:
dijkstra算法里,一旦该点确定最小值后,就不会在更新该点了,但是本题中当前最小值不一定是最终最小值,所以用spfa;
求最大值就是建反边,再来一遍spfa;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=(a);i<(n);++i)
#define rep2(i,a,n) for(register int i=(a);i<=(n);++i)
#define per1(i,n,a) for(register int i=(n);i>(a);i--)
#define per2(i,n,a) for(register int i=(n);i>=(a);i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
#define INF 0x3f3f3f3f
#define tulun() int e[N],ne[N],h[N],w[N],idx;
#define add2(a,b) e[idx]=b,ne[idx]=h[a],h[a]=idx++;
#define add3(a,b,c) w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
#define moreT int T;cin>>T;while(T--)solve();
using namespace std;
typedef long long LL;
typedef double dob;
const int N=2e6+10;
tulun();
int n,m;
int price[N],rh[N],dmin[N],dmax[N],st[N];
void add(int *h,int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void spfa(int *d,int start,int *h,bool flag)
{
queue<int>q;
memset(st,0,st);
if(flag)memset(d,0x3f,dmin);
q.push(start);
d[start]=price[start];
while(q.size())
{
int t=q.front();
q.pop();
st[t]=0;
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
if(flag&&d[j]>min(d[t],price[j])||!flag&&d[j]<max(d[t],price[j]))
{
if(flag)d[j]=min(d[t],price[j]);
else d[j]=max(d[t],price[j]);
if(!st[j])
{
st[j]=1;
q.push(j);
}
}
}
}
}
signed main()
{
quick_cin();
cin>>n>>m;
memset(h,-1,h);
memset(rh,-1,rh);
rep2(i,1,n)cin>>price[i];
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
add(h,a,b),add(rh,b,a);
if(c==2)add(h,b,a),add(rh,a,b);
}
spfa(dmin,1,h,1);
spfa(dmax,n,rh,0);
int ans=0;
rep2(i,1,n)ans=max(ans,dmax[i]-dmin[i]);
cout<<ans;
return 0;
}
2, Almost Equal;
题意:给你数字n,要求创造一个环包含1~2n,且 在环内每取n个数的和,这些和之间的差不能超过1,如果存在环输出,否则NO;
思路:先看样例模拟,
n=3,1,4,5,2,3,6;
很巧妙的发现,从1,4,5开始,后面类似滑动窗口,每进来一个数,就出去一个数,且进出元素的差不超过1;
如果想要和之间差不超1,就只能让按照和+1,-1,+1,-1的顺序来;
拿1,4,5举例,
2进来,1出去,和+1;
3进来,4出去,和-1;
6进来,5出去,和+1;
1进来,2出去,和-1;
4进来,3出去,和+1;
5进来,6出去,和-1,就又是1,4,5了;完美;
所以很容易想到n=偶数是不可行的,
因为n是偶数,就说明+1,-1,+1,-1是偶数对,而折返时取得时相反的序列;
就拿n=4,正序列可以取到,+1,-1,+1,-1,然后开始环取,相反,-1,+1,-1,+1;
总的就是+1,-1,+1,-1,-1,+1,-1,+1;两个-1连续出现!!所以和的差就超过1了!!;
再然后还能发现取得序列的规律;
n=3,1,4,5,2,3,6
n=4,1,4,5,8,2,3,6,7;(供参考找规律)
n=5,1,4,5,8,9,2,3,6,7,10;
n=6,1,4,5,8,9,12,2,3,6,7,10,11;
n每次增长,都只是在原来的序列上变化;
因为1~2n的排列,所以只看前半部分,后半部分因为从小到大,可以直接放进来;
1,4,5
1,4,5,8
1,4,5,8,9
1,4,5,8,9,12
此序列的增长规律就是,第一个元素是1,此后下标是偶数,a[i]=a[i-1]+3,奇数,a[i]=a[i-1]+1;
借此获得前半部分,后半部分直接放即可;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=(a);i<(n);++i)
#define rep2(i,a,n) for(register int i=(a);i<=(n);++i)
#define per1(i,n,a) for(register int i=(n);i>(a);i--)
#define per2(i,n,a) for(register int i=(n);i>=(a);i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
#define INF 0x3f3f3f3f
#define tulun() int e[N],ne[N],h[N],w[N],idx;
#define add2(a,b) e[idx]=b,ne[idx]=h[a],h[a]=idx++;
#define add3(a,b,c) w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
#define moreT int T;cin>>T;while(T--)solve();
using namespace std;
typedef long long LL;
typedef double dob;
const int N=2e6+10;
int n;
int a[N];
int hs[N];
vector<int>ans;
signed main()
{
quick_cin();
cin>>n;
if((n&1)==0)
{
NO;
return 0;
}
a[1]=1;
hs[1]=1;
ans.pb(1);
rep2(i,2,n)
{
if(i&1)a[i]=a[i-1]+1;
else a[i]=a[i-1]+3;
hs[a[i]]=1;
ans.pb(a[i]);
}
rep2(i,1,n*2)
{
if(!hs[i])ans.pb(i);
}
YES;
rep1(i,0,ans.size())cout<<ans[i]<<" ";
return 0;
}