11.12 刷题笔记

11.12 刷题笔记

本来是可以刷题的,但是因为我昨晚在吃完饭回来之后颓了一小会

教练认为我们一点也不累,所以继续考了.....

但是我改完题了,晚上又写了两道。。

CF258D

思路清奇的期望线性性好题!!

说一句话就明白了,逆序对个数的期望就等于每一对数是否能成为逆序对概率加和

\(dp_{i,j}\)表示\(i\)\(j\)大的概率,那么在一开始的序列上就可以直接处理出这个数组

如果交换\(x,y\),首先可以知道要么是\(x \lt y\)要么是\(x \gt y\)

那交换的话\(dp_{x,y}=dp_{y,x}=0.5\)

\(dp_{t,x}=dp_{t,y}=\frac{dp_{t,x}+dp_{t,y}}{2}\)

\(dp_{x,t}=dp_{y,t}=\frac{dp_{x,t}+dp_{y,t}}{2}\)

\(dp\)数组表示了大小关系,还要满足位置关系

满足\(x\)\(y\)前面就行了

code
#include<bits/stdc++.h>
using namespace std;
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1005;
int n,m,a[N];
double f[N][N],ans;
signed main(){
    scanf("%d%d",&n,&m);
    fxt(i,1,n)scanf("%d",&a[i]);
    fxt(i,1,n)fxt(j,1,n)if(a[i]>a[j])f[i][j]=1;
    fxt(i,1,m){
        int x,y;
        scanf("%d%d",&x,&y);
        fxt(j,1,n){
            f[j][x]=f[j][y]=(f[j][x]+f[j][y])*0.5;
            f[x][j]=f[y][j]=1.0-f[j][x];
        }f[x][y]=f[y][x]=0.5;
    }
    fxt(i,1,n)fxt(j,i+1,n)ans+=f[i][j];
    printf("%.10lf",ans);
}

Luogu P1613 跑路

怎么说今天被一道小绿题难的半死。。

总是记不住倍增的预处理原理

一定是先处理一层在处理一层,这样可以保证都被处理到

所以这个先赋值,直接预处理跑\(floyd\)

code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
inline int read(){
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
const int N=55;
const int M=1e4+5;
int n,m;
int to[M*2],nxt[M*2],head[N],rp;
void add_edg(int x,int y){
    to[++rp]=y;
    nxt[rp]=head[x];
    head[x]=rp;
}
bool vis[N];
int dis[N][N];
int st[N][N][65];
signed main(){
    memset(dis,0x3f,sizeof(dis));
    n=read();m=read();
    fo(i,1,m){
        int x=read(),y=read();
        add_edg(x,y);dis[x][y]=1;
        st[x][y][0]=1;
    }
    fo(k,1,64)fo(l,1,n)fo(i,1,n)fo(j,1,n)if(st[i][l][k-1]&&st[l][j][k-1])st[i][j][k]=1,dis[i][j]=1;
    fo(k,1,n)fo(i,1,n)fo(j,1,n)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    printf("%d",dis[1][n]);
}

Luogu P3509 [POI2010]ZAB-Frog

所以尺取法这么好用呢??

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
inline int read(){
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
const int N=1e6+5;
int n,k,m,a[N];
int st[N][65];
signed main(){
    n=read();k=read();m=read();
    fo(i,1,n)a[i]=read();
    int l=1,r=k+1;
    fo(i,1,n){
        if(a[r]-a[i]>a[i]-a[l])st[i][0]=r;
        else st[i][0]=l;
        // cout<<i<<" "<<st[i][0]<<endl;
        while(a[i+1]-a[l]>a[r+1]-a[i+1]&&r<n)r++,l++;
    }
    fo(j,1,60)fo(i,1,n)st[i][j]=st[st[i][j-1]][j-1];
    fo(i,1,n){
        int now=i,num=0;
        fu(j,60,0){
            if(num+(1ll<<j)<=m){
                now=st[now][j];
                num+=(1ll<<j);
            }
        }
        printf("%lld ",now);
    }
}
posted @ 2021-11-12 07:00  fengwu2005  阅读(109)  评论(0)    收藏  举报