20191014

瘦欲@ 提交于 2019-12-01 08:54:30

前言

  • 昨天吉就挂了今天大吉……真准啊。
  • 继续连挂。
  • T2一个很明显的性质没发现,T3白扔20分。
  • 消极消极。

T1

  • 模拟题。跪求B哥轻虐
#include<cstdio>
#include<iostream>
using namespace std;
int const N=9;
int n,m,tp;
int a[N][N];
int stk[N],t,q[N],e;
pair<int,int>b[N*N];
long long ans;
inline int read(){
    int ss(0);char bb(getchar());
    while(bb<48||bb>57)bb=getchar();
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
inline void up(){
    for(register int i=1;i<=n;++i){
        t=e=0;
        for(register int j=n;j;--j)
            if(a[j][i])stk[++t]=a[j][i];
        if(!t)continue;
        q[e=1]=stk[t];
        for(register int j=t-1,la=stk[t];j;--j)
            if(stk[j]==la)q[e]<<=1,ans+=q[e],la=0;
            else q[++e]=la=stk[j];
        for(register int j=1;j<=e;++j){
            if(a[j][i]^q[j])tp=1;
            a[j][i]=q[j];
        }
        for(register int j=e+1;j<=n;++j){
            if(a[j][i])tp=1;
            a[j][i]=0;
        }
    }
    return ;
}
inline void down(){
    for(register int i=1;i<=n;++i){
        t=e=0;
        for(register int j=1;j<=n;++j)
            if(a[j][i])stk[++t]=a[j][i];
        if(!t)continue;
        q[e=1]=stk[t];
        for(register int j=t-1,la=stk[t];j;--j)
            if(stk[j]==la)q[e]<<=1,ans+=q[e],la=0;
            else q[++e]=la=stk[j];
        for(register int j=1;j<=e;++j){
            if(a[n-j+1][i]^q[j])tp=1;
            a[n-j+1][i]=q[j];
        }
        for(register int j=e+1;j<=n;++j){
            if(a[n-j+1][i])tp=1;
            a[n-j+1][i]=0;
        }
    }
    return ;
}
inline void left(){
    for(register int i=1;i<=n;++i){
        t=e=0;
        for(register int j=n;j;--j)
            if(a[i][j])stk[++t]=a[i][j];
        if(!t)continue;
        q[e=1]=stk[t];
        for(register int j=t-1,la=stk[t];j;--j)
            if(stk[j]==la)q[e]<<=1,ans+=q[e],la=0;
            else q[++e]=la=stk[j];
        for(register int j=1;j<=e;++j){
            if(a[i][j]^q[j])tp=1;
            a[i][j]=q[j];
        }
        for(register int j=e+1;j<=n;++j){
            if(a[i][j])tp=1;
            a[i][j]=0;
        }
    }
    return ;
}
inline void right(){
    for(register int i=1;i<=n;++i){
        t=e=0;
        for(register int j=1;j<=n;++j)
            if(a[i][j])stk[++t]=a[i][j];
        if(!t)continue;
        q[e=1]=stk[t];
        for(register int j=t-1,la=stk[t];j;--j)
            if(stk[j]==la)q[e]<<=1,ans+=q[e],la=0;
            else q[++e]=la=stk[j];
        for(register int j=1;j<=e;++j){
            if(a[i][n-j+1]^q[j])tp=1;
            a[i][n-j+1]=q[j];
        }
        for(register int j=e+1;j<=n;++j){
            if(a[i][n-j+1])tp=1;
            a[i][n-j+1]=0;
        }
    }
    return ;
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read(),m=read();
    a[read()][read()]=read(),a[read()][read()]=read();
    for(register int qwq=1,opt,k,v;qwq<=m;++qwq){
        opt=read(),k=read(),v=read();
        tp=0;
        switch(opt){
            case 0:up();break;
            case 1:down();break;
            case 2:left();break;
            case 3:right();break;
        }
        if(!tp)return printf("%d\n%lld",qwq-1,ans),0;
        /*for(register int i=1;i<=n;++i,puts(""))
            for(register int j=1;j<=n;++j)
                printf("%d ",a[i][j]);
        printf("%lld\n",ans);
        if(qwq>=3)return 0;*/
        t=0;
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=n;++j)
                if(!a[i][j])b[++t]=make_pair(i,j);
        int goal=1+k%t;
        a[b[goal].first][b[goal].second]=v;
    }
    printf("%d\n%lld",m,ans);
    return 0;
}
View Code

T2

  • 可以发现最优解的单调区间不超过2,否则必然会有成为累赘的多余区间。
  • 直接DP是$\Theta(N^2)$的,用线段树在$\Theta(NlogN)$的时间复杂度内处理出前后缀max,$\Theta(N)$统计答案即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define L k<<1
#define R k<<1|1
using namespace std;
int const N=11e4;
int n,tot;
int a[N],c[N];
ll f[N][2],maxx[N<<2];
ll ans,tans;
pair<int,int>b[N];
inline int read(){
    int ss(0);char bb(getchar());
    while(bb<48||bb>57)bb=getchar();
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
inline ll _max(ll x,ll y){
    return x>y?x:y;
}
ll ask(int l,int r,int x,int y,int k){
    //printf("%d %d %d %d %d\n",l,r,x,y,k);
    if(x>y)return 0;
    if(l>=x&&r<=y)return maxx[k];
    int mid=l+r>>1;
    ll as=0;
    if(x<=mid)as=ask(l,mid,x,y,L);
    if(y>mid)as=_max(as,ask(mid+1,r,x,y,R));
    return as;
}
inline void update(int k){
    maxx[k]=_max(maxx[L],maxx[R]);
    return ;
}
void add(int l,int r,int x,ll y,int k){
    //printf("!!%d %d %d %lld %d\n",l,r,x,y,k);
    if(l==r){maxx[k]=y;return ;}
    int mid=l+r>>1;
    if(x<=mid)return add(l,mid,x,y,L),update(k);
    return add(mid+1,r,x,y,R),update(k);
}
signed main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read();
    for(register int i=1;i<=n;++i)b[i]=make_pair(a[i]=read(),i);
    sort(b+1,b+n+1);
    for(register int i=1;i<=n;++i)
        c[b[i].second]=i;
    for(register int i=1;i<n;++i)
        add(1,n,c[i],f[i][0]=ask(1,n,1,c[i]-1,1)+a[i],1);
    f[n][0]=ask(1,n,1,c[n]-1,1)+a[n],memset(maxx,0,sizeof(maxx));
    for(register int i=n;i;--i)
        add(1,n,c[i],f[i][1]=ask(1,n,1,c[i]-1,1)+a[i],1);
    for(register int i=1;i<=n;++i)f[i][0]=_max(f[i][0],f[i-1][0]);
    for(register int i=n;i;--i)f[i][1]=_max(f[i][1],f[i+1][1]);
    for(register int i=1;i<=n;++i)
        ans=_max(ans,f[i][0]);
    for(register int i=1;i<n;++i)
        tans=_max(tans,f[i][0]+f[i+1][1]);
    if((ans<<1)>=tans)return printf("%lld.000",ans),0;
    if(tans&1)return printf("%lld.500",tans>>1),0;
    return printf("%lld.000",tans>>1),0;
}
View Code

T3

  • 用随机化模拟偏转角度进行排序,跑最大生成树。
  • 正确率较高。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#define ll long long
using namespace std;
int const N=51,M=203;
int n,m;
int fa[N];
ll ans;
double xx,yy;
struct node{
    int u,v;
    ll a,b;
}s[M];
inline int read(){
    int ss(0),pp(1);char bb(getchar());
    for(;bb<48||bb>57;bb=getchar())if(bb=='-')pp=-1;
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss*pp;
}
inline ll _max(ll x,ll y){
    return x>y?x:y;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline bool cmp(node x,node y){
    return xx*x.a+yy*x.b<xx*y.a+yy*y.b;
}
int main(){
    //freopen("2.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read(),m=read();
    for(register int i=1;i<=m;++i)
        s[i].u=read(),s[i].v=read(),s[i].a=read(),s[i].b=read();
    srand(time(NULL));
    register int p,q;
    for(register int h=1;h<=23333;++h){
        xx=(rand()%20000-10000)*0.00001,yy=(rand()%20000-10000)*0.00001;
        sort(s+1,s+m+1,cmp);
        p=0,q=0;
        for(register int i=1;i<=n;++i)fa[i]=i;
        for(register int i=1;i<=m;++i){
            int x=find(s[i].u),y=find(s[i].v);
            if(x==y)continue;
            fa[x]=y,p+=s[i].a,q+=s[i].b;
        }
        ans=_max(ans,1ll*p*p+1ll*q*q);
    }
    printf("%.6lf",sqrt(ans));
    return 0;
}
View Code
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!