2018 11.2 PION模拟赛

期望:100 + 50 + 30 = 180

实际:0 + 50 + 30 =80

期望:100   实际:0

数值有负数,边界应该设为-0x7f       此处 gg

/*
期望的分:50+ 
*/
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,tot,ans;
int f[MAXN];
int num[MAXN],w[MAXN],a[MAXN];
int lchild[MAXN],rchild[MAXN]; 
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void pre(int now){
    if(now==0)    return ;
    num[++tot]=now;
    if(rchild[now])    pre(rchild[now]);
    if(lchild[now])    pre(lchild[now]);
}
int main(){
    //freopen("lpp.in","r",stdin);
    freopen("point.in","r",stdin);
    freopen("point.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)    w[i]=read();
    for(int i=1;i<=n;i++){
        lchild[i]=read();
        rchild[i]=read();
    }
    pre(1);
    for(int i=1;i<=n;i++)    a[i]=w[num[i]];
    memset(f,-0x7f,sizeof(f));
    for(int i=1;i<=n;i++){
        if(a[i]>f[ans])    f[++ans]=a[i];
        else{
            int x=lower_bound(f+1,f+1+ans,a[i])-f;
            f[x]=a[i];    
        }
    }
    printf("%d\n",ans);
}
/*
10
-77 -24 21 6 -4 -69 -1 -19 76 -1 
5 2
7 8
0 0
6 9
10 4
0 3
0 0
0 0
0 0
0 0
*/
100

/*
期望:50+;
*/
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
long long ans;
int a[100010],b[100010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void work(int l,int r){
    if(l==r)    return; 
    int mid=(l+r)/2; 
    work(l,mid);
    work(mid+1,r);
    int i=l,j=mid+1;
    int nb=0;
    while(i<=mid||j<=r){
        if(i>mid)    b[++nb]=a[j++];
        else if(j>r)    b[++nb]=a[i++];
        else{
            if(a[i]<a[j])    b[++nb]=a[i++];
            else{
                b[++nb]=a[j++];
                ans+=mid-i+1;
            }
        }
    }
    for(i=l;i<=r;++i)    a[i]=b[i-l+1];
}
int main(){
    //freopen("lpp.in","r",stdin);
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n=read();
    if(n==1){
        int x=read();int y=read();
        if(x>y)    swap(x,y);
        printf("%d\n",(y-x)*2-1);
    }
    else if(n==2){
        int x1=read();int y1=read();
        int x2=read();int y2=read();
        if(x1>y1)    swap(x1,y1);
        if(x2>y2)    swap(x2,y2);
        if(x1==x2&&y1==y2){ printf("0\n");return 0; }
        if(x1<x2&&y1>y2||x2<x1&&y2>y1){ printf("%d\n",(y1-x1)*2-1+(y2-x2)*2-1);return 0;}
        if(x2>y1||x1>y2){ printf("%d\n",(y1-x1)*2-1+(y2-x2)*2-1);return 0;}
        if(y1==x2||y2==x1){ printf("%d\n",(y1-x1)*2-1+(y2-x2)*2-1-1);return 0;}
        if(x2>x1&&x2<y1){ printf("%d\n",(y1-x1)*2-1+(y2-x2)*2-1-1-(y1-x2));return 0;}
        if(x1>x2&&x1<y2){ printf("%d\n",(y1-x1)*2-1+(y2-x2)*2-1-1-(y2-x1));return 0;}
    }
    else{
        for(int i=1;i<=100000;i++)    a[i]=i;
        for(int i=1;i<=n;i++){
            int x=read();int y=read();
            swap(a[x],a[y]);
        }
        work(1,100000);
        printf("%d\n",ans);
    }
}
50分暴力
/*
分成三部分讨论
    第一部分:讨论修改位置的数对答案的贡献
    第二部分:讨论修改部分的区间对答案的贡献。
    第三部分:讨论余下未修改的对答案的贡献。
       可以发现,第一部分用树状数组暴力求逆序对维护。第二部分前缀和差分维护,第三部分的贡献为0.
*/
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
long long ans;
int x[100010],y[100010],pos[200010];
int date[200010],T[200010],sum[200010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int lowbit(int x){
    return x&(-x);
}
void add(int x){
    for(int i=x;i<=n*2;i+=lowbit(i))    T[i]++;
}
long long  query(int x){
    long long bns=0;
    for(int i=x;i;i-=lowbit(i))    bns+=T[i];
    return bns;
}
int main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++){
        x[i]=read();
        y[i]=read();
        date[i]=x[i];date[i+n]=y[i];
        pos[i]=i;pos[i+n]=i+n;
    }
    sort(date+1,date+1+2*n);
    int num=unique(date+1,date+1+2*n)-date-1;
    for(int i=1;i<=num;i++)    sum[i]=sum[i-1]+date[i]-date[i-1]-1;
    for(int i=1;i<=n;i++){
        x[i]=lower_bound(date+1,date+1+num,x[i])-date;
        y[i]=lower_bound(date+1,date+1+num,y[i])-date;
        swap(pos[x[i]],pos[y[i]]);
    }
    for(int i=num;i>=1;i--){
        ans+=query(pos[i]);
        ans+=abs(sum[pos[i]]-sum[i]);
        add(pos[i]);
    }
    printf("%I64d",ans);
}
100

/*
期望:30
*/
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,q,tot;
int dad[200010],num[200010];
int to[400010],net[400010],head[200010];
int col[200010],vis[200010],into[200010];
struct nond{
    int l,r,col,vi;
}v[200010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
}
void bfs(int s,int a,int b){
    queue<int>que;
    if(col[s]==a)    col[s]=b;
    que.push(s);vis[s]=1;
    while(!que.empty()){
        int now=que.front();
        que.pop();
        for(int i=head[now];i;i=net[i])
            if(!vis[to[i]]){
                if(col[to[i]]==a)    col[to[i]]=b;
                if(col[to[i]]==col[s]){
                    vis[to[i]]=1;
                    que.push(to[i]);
                }
            }
    }
}
int main(){
    //freopen("lpp.in","r",stdin);
    freopen("simulator.in","r",stdin);
    freopen("simulator.out","w",stdout);
    n=read();q=read();
    for(int i=1;i<=n;i++)    col[i]=read();
    for(int i=1;i<n;i++){
        int u=read();
        int v=read();
        add(u,v);add(v,u);
        into[u]++;into[v]++;
    }
    if(n<=1000){
        for(int i=1;i<=q;i++){
            int a=read();int b=read();
            memset(vis,0,sizeof(vis));
            int num=0;
            for(int j=1;j<=n;j++)
                if(!vis[j]){
                    bfs(j,a,b);
                    num++;
                }
            printf("%d\n",num);
        }
    }
}
30分暴力
/*
我们考虑优化合并操作,我们发现把x变成y和把y变成x得到的答案是相同的,
所以我们在合并的时候以及更改颜色的时候都是把颜色少的改成颜色多的,并
且维护每种颜色实际的vector是哪个,然后就相当于启发式合并。
每个点的复杂度是他的度数乘以它被统计答案的次数,
最差情况下每个点也只会被统计logN次答案,那么复杂度就是logN *  
等于2NlogN
*/
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,q,tot,ans;
int id[200010];
int col[200010],size[200010],dad[200010];
int to[400010],net[400010],head[200010];
vector<int>vec[200010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
}
void dfs(int now){
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            dad[to[i]]=now;
            dfs(to[i]);
            if(col[to[i]]!=col[now])    ans++;
        }
}
void change1(int now){
    for(int i=head[now];i;i=net[i])
        if(col[to[i]]!=col[now])    ans--;
}
void change2(int now){
    for(int i=head[now];i;i=net[i])
        if(col[to[i]]!=col[now])    ans++;
}
int main(){
    freopen("simulator.in","r",stdin);
    freopen("simulator.out","w",stdout);
    n=read();q=read();
    for(int i=1;i<=n;i++){
        id[i]=i;
        col[i]=read();
        size[col[i]]++;
        vec[col[i]].push_back(i);
    }
    for(int i=1;i<n;i++){
        int u=read();
        int v=read();
        add(u,v);add(v,u);
    }
    add(0,1);add(1,0);col[0]=200010;
    dfs(0);//cout<<ans;
    for(int i=1;i<=q;i++){
        int a=read();int b=read();
        int xn=id[a],yn=id[b];
        if(size[xn]<=size[yn]){
            for(int j=0;j<vec[xn].size();j++){
                change1(vec[xn][j]);
                vec[yn].push_back(vec[xn][j]);
            }
            for(int j=0;j<vec[xn].size();j++)    col[vec[xn][j]]=yn;
            for(int j=0;j<vec[xn].size();j++)    change2(vec[xn][j]);
            size[yn]+=size[xn];
            size[xn]=0;id[b]=yn;
            vec[xn].clear();
        }
        else{
            for(int j=0;j<vec[yn].size();j++){
                change1(vec[yn][j]);
                vec[xn].push_back(vec[yn][j]);
            }
            for(int j=0;j<vec[yn].size();j++)    col[vec[yn][j]]=xn;
            for(int j=0;j<vec[yn].size();j++)    change2(vec[yn][j]);
            size[xn]+=size[yn];
            size[yn]=0;
            id[b]=xn;id[a]=0;
            vec[yn].clear();
        }
        printf("%d\n",ans);
    }
}
/*
6 3
1 2 1 1 1 2
1 2
1 3
2 4
2 5
5 6

*/
100

 

posted @ 2018-11-02 16:31  一蓑烟雨任生平  阅读(209)  评论(0编辑  收藏  举报