这道题其实就是就是求逆序对数目,然后我们可以想到第一个数组里第k大的数对应第二个数组里第k大的数
求逆序对个数第一个想到的就是归并排序了
#include
#include
#include
using namespace std;
typedef long long ll;
const int MAXN = 1e5+5, MOD = 99999997;
int n, answer;
struct name {
int num, Idx;
}a[MAXN], b[MAXN];
int Tmp[MAXN], Tmp2[MAXN];
bool comp(name x, name y){ return x.num < y.num; }
void Merge(int left, int right)
{
if(left >= right) return ;
int mid = left + (right - left) / 2;
Merge(left, mid);
Merge(mid+1, right);
int i = left, j = mid+1, k = left;
while(i<=mid && j<=right)
{
if(Tmp[i] > Tmp[j])
{
Tmp2[k++] = Tmp[j++];
answer += mid-i+1;
answer %= MOD;
}
else Tmp2[k++] = Tmp[i++];
}
while(i<=mid) Tmp2[k++] = Tmp[i++];
while(j <= right) Tmp2[k++] = Tmp[j++];
for(int l = left; l<= right; l++)
{
Tmp[l] = Tmp2[l];
}
}
int main()
{
// freopen("match.in","r",stdin);
// freopen("match.out","w",stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i].num);
a[i].Idx = i;
}
for(int i = 1; i <= n; i++)
{
scanf("%d", &b[i].num);
b[i].Idx = i;
}
sort(a+1, a+n+1, comp);
sort(b+1, b+n+1, comp);
for(int i = 1; i <= n; i++)
{
Tmp[a[i].Idx] = b[i].Idx;
}
Merge(1, n);
printf("%d", answer);
return 0;
}
可以想到用最大生成树,求到了最大生成树之后,我们便考虑如何求出两个节点之间最小边权的最大值,因为这两点之间的路径是唯一的,于是我们可以通过LCA求出答案。
#include
#include
#include
using namespace std;
typedef long long ll;
const int MAXN = 1e6+5;
int w[MAXN][21],p[MAXN][21],head[MAXN],deep[MAXN],fa[MAXN];
struct nodea{ int x,y,c; } t[MAXN];
struct nodeb{ int x,y,c,g; } h[MAXN];
int INF = 999999999, len, n, m, q;
void px(int l, int r)
{
int x=l,y=r, mid=t[(l+r)/2].c;
while(x <= y)
{
while(t[x].c > mid) x++;
while(t[y].cif(x <= y)
{
nodea pt = t[x];
t[x] = t[y];
t[y] = pt;
x++;
y--;
}
}
if(l < y) px(l,y);
if(xint min(int x,int y){ return xint init()
{
for(int i = 1; i <= n; i++)
{
fa[i] = i;
head[i] = 0;
deep[i] = 0;
}
}
void ins(int x, int y, int c)
{
len++;
h[len].x = x;
h[len].y = y;
h[len].c = c;
h[len].g = head[x];
head[x] = len;
}
int find(int t)
{
if(fa[t] == t) return t;
else return fa[t]=find(fa[t]);
}
void kruskal()
{
int p = 0;
for(int i = 1; i <= m; i++)
{
int tx = find(t[i].x);
int ty = find(t[i].y);
if(tx != ty)
{
fa[tx] = ty;
ins(t[i].x,t[i].y,t[i].c);
ins(t[i].y,t[i].x,t[i].c);
p++;
if(p == n-1) break;
}
}
}
void dfs(int u)
{
for(int i = head[u]; i > 0; i=h[i].g)
{
int y = h[i].y;
if(deep[y]==0)
{
deep[y]=deep[u]+1;
p[y][0]=u;
w[y][0]=h[i].c;
dfs(y);
}
}
}
void ycl()
{
for(int i = 1; i <= n; i++)
{
if(deep[i] == 0)
{
deep[i] = 1;
p[i][0] = 0;
dfs(i);
}
}
dfs(1);
for(int i = 1; i <= 20; i++)
{
for(int x = 1; x <= n; x++)
{
p[x][i] = p[p[x][i-1]][i-1];
w[x][i]=min(w[x][i-1], w[p[x][i-1]][i-1]);
}
}
}
int lca(int x,int y)
{
int ans=INF;
if(deep[x] < deep[y])
{
int t = x;
x = y;
y = t;
}
for(int i = 20; i >= 0; i--)
if(deep[p[x][i]] >= deep[y])
{
ans = min(ans,w[x][i]);
x = p[x][i];
}
if(x == y) return ans;
for(int i = 20; i >= 0; i--)
if(p[x][i] != p[y][i])
{
ans = min(ans, min(w[x][i], w[y][i]));
x = p[x][i];
y = p[y][i];
}
ans = min(ans, min(w[x][0], w[y][0]));
return ans;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &t[i].x, &t[i].y, &t[i].c);
px(1, m);
init();
kruskal();
ycl();
scanf("%d", &q);
for(int i = 1; i <= q; i++)
{
int dx = 0, dy = 0;
scanf("%d%d", &dx, &dy);
if(find(dx) != find(dy)) printf("-1\n");
else printf("%d\n",lca(dx,dy));
}
return 0;
}