FZU 2059 MM (并查集+排序插入)

Problem 2059 MM

Accept: 109    Submit: 484
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

There is a array contain N(1<N<=100000) numbers. Now give you M(1<M<10000) query.

Every query will be:

1 x : ask longest substring which every number no less than x

2 y x : change the A[y] to x. there are at most change 10 times.

For each ask can you tell me the length of longest substring.

 Input

There are multiple tests.

each test first line contain two integer numbers N M,second line contain N integer numbers.

Next M lines each line will be:

1 x : ask longest substring which every number no less than x

2 y x : change the A[y] to x. there are at most change 10 times.

0 < N <= 100000, 0 < M <= 10000, -1000000000 <= A[i] <= 1000000000

 Output

Each ask output the length of longest substring .

 Sample Input

5 5 1 2 3 2 1 1 2 1 3 2 3 1 1 2 1 3

 Sample Output

3 1 1 0
 
题意:  给一个数列,两种操作,第一种操作是输入一个x,查找一个子串满足每个元素的值都不小于x且长度最大,输出这个最大值,第二个操作是输入x和y,修改a[y]=x,第二个操作最多只有十次
 
思路: o(nlogn)预处理,o(logn)查询。由于修改操作只有10次,所以每次修改都直接暴力预处理一遍,然后考虑没有修改操作的情况。
预处理方法:把数列值排序一下,然后从大到小逐个插入,用并查集维护插入的这个点能连接的最长长度,在这个过程中维护一个最大值,最大值就是答案了。
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1e9;
const double eps = 1e-6;
const int N = 100010;
int cas = 1;

struct _node{
    int pos,val,ans;
    friend bool operator < (const _node &a, const _node &b)
    {
        return a.val < b.val;
    }
};
int n,m;
int fa[N],sum[N],b[N],mxval;
_node a[N];

int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

void un(int u,int v)
{
    u=find(u), v=find(v);
    fa[u]=v;
    sum[v]+=sum[u];
}

void pre()
{
    memset(sum,0,sizeof(sum));
    mxval = -INF-10;
    for(int i=0;i<n;i++) fa[i]=i;
    for(int i=0;i<n;i++)
    {
        a[i].val=b[i],a[i].pos=i;
        if(a[i].val > mxval) mxval = a[i].val;
    }
    sort(a,a+n);
    int mx = 0;
    for(int i=n-1;i>=0;i--)
    {
        sum[a[i].pos]=1;
        if(sum[a[i].pos-1]) un(a[i].pos-1,a[i].pos);
        if(sum[a[i].pos+1]) un(a[i].pos+1,a[i].pos);
        if(mx < sum[find(a[i].pos)]) mx = sum[fa[a[i].pos]];
        a[i].ans = mx;
    }
}

int solve(int x)
{
    _node t;
    t.val=x;
    int id = lower_bound(a,a+n,t) - a;
    return a[id].ans;
}

void run()
{
    for(int i=0;i<n;i++)
        scanf("%d",b+i);
    pre();
    int x,y,op;
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&x);
            if(x>mxval) puts("0");
            else printf("%d
",solve(x));
        }
        else
        {
            scanf("%d%d",&y,&x);
            b[y-1]=x;
            pre();
        }
    }
}

int main()
{
    #ifdef LOCAL
    freopen("case.txt","r",stdin);
    #endif
    while(scanf("%d%d",&n,&m)!=EOF)
        run();
    return 0;
}
原文地址:https://www.cnblogs.com/someblue/p/4048256.html