11.2NOIP模拟赛

/*
根右左遍历后最长上升子序列
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long LL;

inline LL read()
{
    char c=getchar();LL num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

const int N=1e5+5;

int n;
LL w[N];
int son[N][2];

LL dfn[N],tim;
void dfs(int u)
{
    dfn[++tim]=w[u];
    if(son[u][1]!=0)
        dfs(son[u][1]);
    if(son[u][0]!=0)
        dfs(son[u][0]);
}

LL lis[N],len;
int main()
{
    freopen("point.in","r",stdin);
    freopen("point.out","w",stdout);
     int size = 256 << 20; // 256MB  
        char *p = (char*)malloc(size) + size;  
        __asm__("movl %0, %%esp\n" :: "r"(p));
 
    n=read();
    for(int i=1;i<=n;++i)
        w[i]=read();
    for(int i=1;i<=n;++i)
        son[i][0]=read(),son[i][1]=read();
    dfs(1);
    lis[len=1]=dfn[1];
    for(int i=2;i<=tim;++i)
    {
        if(dfn[i]>lis[len]) lis[++len]=dfn[i];
        else lis[lower_bound(lis+1,lis+len+1,dfn[i])-lis]=dfn[i];
    }
    cout<<len;
    fclose(stdin);fclose(stdout);
    return 0;
}

/*
序列分为移动的序列和未移动的序列两部分
询问离散化后 
对于移动的序列,抽出来树状数组统计逆序对
对于未移动的序列,想办法能直接统计答案
首先维护哪些数未被移动过,然后对于未被移动过的数求前缀和sum[i] 
这样就得到了1~i中未被移动过的数的个数,进而能O(1)得出每段区间未被移动的数的个数。
考虑一个移动了的元素,从i向前移动到了j,那么他对答案的贡献,就是sum[j,i]
因为向前移动后[j,i]这段区间所有数都比他小。
同理一个元素从i向后移动到了j,那么他对答案的贡献为sum[i,j]
所以未被移动的元素对答案的贡献和就是Σabs(sum[原来位置]-sum[移动后的位置]) 
*/
#include<bits/stdc++.h>

#define N 200007
#define ll long long

using namespace std;
int n,m,cnt,num;
ll ans;
ll pos[N],a[N],sum[N];
struct node{
    int L,R;
}ask[N];

struct BIT_{
    
    int n;ll a[N];
    
    static int lowbit(int x){
        
        return x & -x;
    }
    
    void clear(){
        
        for(int i=1;i<=n;i++) a[i]=0;
    }
    
    ll query(int pos){
        
        ll ans=0;
        for(int i=pos;i>0;i-=lowbit(i)) ans+=a[i];
        return ans;
    }
    
    void update(int pos,int val){
        
        for(int i=pos;i<=n;i+=lowbit(i)) a[i]+=val;
    }
}bit;

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

void discrete()
{
    for(int i=1;i<=n;i++)
    {
        ask[i].L=read();ask[i].R=read();
        a[i]=ask[i].L;a[i+n]=ask[i].R;
        pos[i]=i;pos[i+n]=i+n;
    }
    sort(a+1,a+n*2+1);
    num=unique(a+1,a+n*2+1)-a-1;
    for(int i=1;i<=num;i++) sum[i]=sum[i-1]+a[i]-a[i-1]-1;
    for(int i=1;i<=n;i++)
    {
        ask[i].L=lower_bound(a+1,a+num+1,ask[i].L)-a;
        ask[i].R=lower_bound(a+1,a+num+1,ask[i].R)-a;
        swap(pos[ask[i].L],pos[ask[i].R]);
    }
}

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n=read();discrete();
    bit.n=n<<1; bit.clear();
    for(int i=num;i>=1;i--)
    {
        ans+=bit.query(pos[i]);
        ans+=abs(sum[pos[i]]-sum[i]);
        bit.update(pos[i],1);
    }
    cout<<ans<<endl;
    return 0;
}

/*
bzoj1483 放到树上
见https://www.cnblogs.com/L-Memory/p/9898249.html 
同理 vector+启发式合并。 
*/
#include<bits/stdc++.h>

#define ll long long
#define M 200010
using namespace std;
int read()
{
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}

int note[M], sz[M], cor[M], id[M];
vector<int>to[M], to1[M];
int n, q, ans;
void dfs(int now, int fa)
{
    if(cor[now] != 0 && cor[now] != cor[fa]) ans++;
    for(int i = 0; i < to[now].size(); i++)
    {
        int vj = to[now][i];
        if(vj == fa) continue;
        dfs(vj, now);
    }
}

void del(int x)
{
    for(int i = 0; i < to[x].size(); i++)
    {
        int vj = to[x][i];
        if(cor[vj] != cor[x]) ans--;
    }
}
void insert(int x)
{
    for(int i = 0; i < to[x].size(); i++)
    {
        int vj = to[x][i];
        if(cor[vj] != cor[x]) ans++;
    }
}
int tot = 0, tot2 = 0;
int main()
{
    freopen("simulator.in", "r", stdin);
    freopen("simulator.out", "w", stdout);
    n = read(), q = read();
    for(int i = 1; i <= n; i++) cor[i] = read(), sz[cor[i]]++, to1[cor[i]].push_back(i), id[i] = i, note[i] = i;
    for(int i = 1; i < n; i++)
    {
        int vi = read(), vj = read();
        to[vi].push_back(vj), to[vj].push_back(vi);
    }
    to[1].push_back(0), cor[0] = 0x3e3e3e3e;
    dfs(1, 0);
    while(q--)
    {
        int x = read(), y = read();
        int xn = id[x], yn = id[y];
        if(sz[xn] < sz[yn])
        {
            tot += sz[xn], tot2 += to1[xn].size();
            for(int i = 0; i < to1[xn].size(); i++)
            {
                int op = to1[xn][i];
                del(op);
                to1[yn].push_back(op);
            }
            for(int i = 0; i < to1[xn].size(); i++)
            {
                int op = to1[xn][i];
                cor[op] = yn;
            }
            for(int i = 0; i < to1[xn].size(); i++)
            {
                int op = to1[xn][i];
                insert(op);
            }
            to1[xn].clear();
            sz[yn] += sz[xn];
            sz[xn] = 0;
            id[x] = 0;
        }
        else
        {
            tot+=sz[yn], tot2 += to1[yn].size();
            for(int i = 0; i < to1[yn].size(); i++)
            {
                int op = to1[yn][i];
                del(op);
                to1[xn].push_back(op);
            }
            for(int i = 0; i < to1[yn].size(); i++)
            {
                int op = to1[yn][i];
                cor[op] = xn;
            }
            for(int i = 0; i < to1[yn].size(); i++)
            {
                int op = to1[yn][i];
                insert(op);
            }
            to1[yn].clear();
            sz[xn] += sz[yn];
            sz[yn] = 0;
            id[y] = xn;
            id[x] = 0;
        }
        cout << ans << "\n";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/L-Memory/p/9898342.html