B
很明显,第一位肯定是能比较出大小的
然后1 换a过来,2 换b过来 3 a也换b也换
法1
当时的乱搞写法
存下位置,排序值,st表找合适值域中位置最小值
int n,a[N],lg[N],minn[N][50],ans; struct node { int val; int pos; bool operator<(const node &rhs)const{ return val<rhs.val; } }b[N]; void solve(){ lg[0]=-1; ans=inf; scanf("%lld",&n); for(int i=1;i<=n;++i)scanf("%lld",&a[i]); for(int i=1;i<=n;++i){ lg[i]=lg[i/2]+1; scanf("%lld",&b[i].val); b[i].pos=i; } sort(b+1,b+1+n); for(int i=1;i<=n;i++){ minn[i][0]=b[i].pos; } for(int i=1;i<=lg[n];i++){ for(int j=1;j+(1<<i)-1<=n;j++){ minn[j][i]=min(minn[j][i-1],minn[j+(1<<(i-1))][i-1]); } } for(int i=1;i<=n;i++){ int l=(a[i]+1)/2; int r=n; int len=lg[r-l+1]; ans=min(ans,i-2+min(minn[l][len],minn[r-(1<<(len))+1][len])); } printf("%lld ",ans); }
法2
按ai的值上升,找合适的bi
类似于单调栈的感觉
对于ai值从小到大,bi的位置一定是单调上升的
证明
假设当前ai值 为 x 找到 b的pos为合适
若bpos 小于x + 2 pos后移
若bpos 大于x + 2 pos不变
假设pos点不是最优的,pos位置前存在 pos‘ 使得 bpos’ 大于 x
根据前面的移动规则, 指针不会移动到pos位置,因为 bpos’ 指针会停留在pos‘
得到pos点最优
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i]; int ans = n; for(int i=1, j=0;i<2*n;i+=2) { while(b[j]<i) j++; c[i] = j; } for(int i=0;i<n;i++) ans = min(ans, c[a[i]]+ i);
C
记录一下 轮数 和 编号
然后优先队列保证小轮数先更新
章节编号大的同一轮
编号小的 下一轮
#include<bits/stdc++.h> #define inf 1e18 #define ll long long #define ull unsigned long long #define int long long #define PI acos(-1.0) #define PII pair<int,int> using namespace std; const int N = 1e6+7 , M = N * 2; const int p = 998244353; int num,x,n,ans; int in[N]; int h[N], e[N], ne[N], idx; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } bool topo(){ priority_queue<PII, vector<PII>, greater< PII > > q; int cnt = 0; for(int i = 1; i <= n ;++i){ if(in[i] == 0){ cnt++; q.push({1,i}); } } while(!q.empty()){ ans = q.top().first; int pos = q.top().second; q.pop(); for (int i = h[pos]; i != -1; i = ne[i]) { int j = e[i]; --in[j]; if(in[j] == 0) { cnt++; if(j > pos) q.push({ans,j}); else q.push({ans+1,j}); } } } //cout << n << cnt <<" --- "; return cnt == n ; } void solve(){ ans=-1;idx=0; scanf("%lld",&n); for(int i=1;i<=n;++i) h[i] = -1; for(int i=1;i<=n;++i){ scanf("%lld%",&num); in[i]=num; while(num--){ scanf("%lld",&x); add(x,i); } } if(topo()) printf("%lld ",ans); else printf("-1 "); } signed main(){ int t=1; scanf("%lld",&t); while(t--){ solve(); } return 0; }