zoukankan      html  css  js  c++  java
  • csp-s模拟测试44「D·E·F」

    用心出题,用脚造数据

    乱搞场

     1 #include<bits/stdc++.h>
     2 #define re register
     3 #define int long long
     4 #define inf 0x7ffffffffffffff
     5 using namespace std;
     6 int n,a[100010],b[100010],ans=inf;
     7 double st,ed;
     8 inline int read(){
     9     re int a=0,b=1; re char ch=getchar();
    10     while(ch<'0'||ch>'9')
    11         b=(ch=='-')?-1:1,ch=getchar();
    12     while(ch>='0'&&ch<='9')
    13         a=(a<<3)+(a<<1)+(ch^48),ch=getchar();
    14     return a*b;
    15 }
    16 inline int max(re int x,re int y){if(x>y) return x; return y;}
    17 inline int min(re int x,re int y){if(x<y) return x; return y;}
    18 inline void dfs(re int x,re int l,re int r,re int ll,re int rr){
    19     if(1ll*(r-l)*(rr-ll)>ans) return ;
    20     if(x>n){
    21         ans=1ll*(r-l)*(rr-ll); 
    22         ed=clock();
    23         if((ed-st)/1e6>=1.99){
    24             printf("%lld
    ",ans);
    25             exit(0);
    26         }
    27         return ; 
    28     }
    29     dfs(x+1,max(l,a[x]),min(r,a[x]),max(ll,b[x]),min(rr,b[x]));
    30     dfs(x+1,max(l,b[x]),min(r,b[x]),max(ll,a[x]),min(rr,a[x]));
    31 }
    32 signed main(){
    33 //    freopen("in.txt","r",stdin);
    34     n=read();if(n==1){puts("1");return 0;}
    35     for(re int i=1;i<=n;++i){
    36         a[i]=read(),b[i]=read();
    37         if(a[i]<b[i]) a[i]^=b[i]^=a[i]^=b[i];
    38     }
    39     st=clock();
    40     dfs(1,0,inf,0,inf);
    41     printf("%lld
    ",ans);
    42     return 0;
    43 }
    随机化
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<bits/stdc++.h>
     6 #define reg register
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn=1e5+5,INF=2e9;
    10 inline void read(int &x)
    11 {
    12     x=0;char c=getchar();
    13     while(c<'0'||c>'9') c=getchar();
    14     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48,c=getchar();
    15 }
    16 ll ans;
    17 int S,T,n,tot,L[maxn][2],R[maxn][2],L2[2],R2[2],tmp[2],yet[maxn];
    18 struct ball{
    19     int x[2];
    20 }c[maxn];
    21 struct wh{
    22     int x,id,f;
    23     bool friend operator < (const wh a,const wh b) {return a.x<b.x;}
    24 }g[maxn<<1];
    25 void dfs(int x)
    26 {
    27     T=clock();
    28     if(T-S>1500000) {printf("%lld
    ",ans);exit(0);}
    29     if(x!=1&&1LL*(L[x-1][1]-L[x-1][0])*(R[x-1][1]-R[x-1][0])>ans) return ;
    30     if(x==n+1) {ans=1LL*(L[x-1][1]-L[x-1][0])*(R[x-1][1]-R[x-1][0]);return ;}
    31     if(c[x].x[0]>c[x].x[1]) swap(c[x].x[0],c[x].x[1]);
    32     for(reg int j=0;j<=1;++j)    
    33     {
    34         L[x][0]=min(L[x-1][0],c[x].x[j]);
    35         L[x][1]=max(L[x-1][1],c[x].x[j]);
    36         R[x][0]=min(R[x-1][0],c[x].x[j^1]);
    37         R[x][1]=max(R[x-1][1],c[x].x[j^1]);
    38         dfs(x+1);
    39     }
    40 }
    41 int main()
    42 {
    43     srand(time(NULL));
    44     S=clock();
    45 //    freopen("ans.in","r",stdin);
    46 //    freopen("b.out","w",stdout);
    47     read(n);
    48     for(reg int i=1;i<=n;++i)
    49     {
    50         read(c[i].x[0]),read(c[i].x[1]);
    51         g[++tot]=(wh){c[i].x[0],i,0};
    52         g[++tot]=(wh){c[i].x[1],i,1};
    53     }
    54     reverse(c+1,c+n+1);
    55     sort(g+1,g+tot+1);
    56     ans=1e18;ans+=5;
    57     int l=1,r=tot,k=0;
    58     memset(yet,0xFF,sizeof(yet));
    59     while(k<n)
    60     {
    61         while(yet[g[l].id]!=-1) ++l;
    62         yet[g[l].id]=g[l].f;++k;
    63         if(k==n) break;
    64         while(yet[g[r].id]!=-1) --r;
    65         yet[g[r].id]=g[r].f;++k;
    66     }
    67     L[0][0]=R[0][0]=L2[0]=R2[0]=INF;
    68     for(reg int i=1;i<=n;++i)
    69     {
    70         L2[0]=min(L2[0],c[i].x[yet[i]]);
    71         L2[1]=max(L2[1],c[i].x[yet[i]]);
    72         R2[0]=min(R2[0],c[i].x[yet[i]^1]);
    73         R2[1]=max(R2[1],c[i].x[yet[i]^1]);
    74     }
    75     ans=1LL*(L2[1]-L2[0])*(R2[1]-R2[0]);
    76     dfs(1);
    77     printf("%lld
    ",ans);
    78     return 0;
    79 }
    clock

    垃圾zzn当然什么也不会啦,乱搞什么也没打

    D

    考试时想到正解,没打,觉得这仅仅是个简单的剪枝,没想到啊

    题意

    求$(r-l+1)*gcd(a[l],a[l+1],.....,a[r])$最大值

    题解

    垃圾zzn没打正解,类正解多$log$用来二分了,常数较小

    $gcd$总需要求,求次数太多了

    考虑二分,维护$gcd$从$mid$前缀和后缀和

    这样你就有$50$分了

    考虑$gcd$变化次数小于是维护单调队列,很简单

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define A 333333
     5 ll a[A],suml[A],sumr[A],dll[A],dlr[A];
     6 ll ans=0,n;
     7 ll gcd(ll x,ll y){
     8     if(y==0) return x;
     9     return gcd(y,x%y);
    10 }
    11 void solve(ll l,ll r){
    12     if(l==r) return ;
    13     ll mid=(l+r)>>1,rnow=mid+1,lnow=mid;
    14     suml[lnow]=a[lnow],sumr[rnow]=a[rnow];
    15     dll[0]=0,dlr[0]=0;
    16     while(lnow>l){
    17         lnow--;
    18         suml[lnow]=gcd(suml[lnow+1],a[lnow]);
    19         if(suml[lnow]!=suml[lnow+1])
    20             dll[++dll[0]]=lnow+1;
    21     }
    22     dll[++dll[0]]=l;
    23     while(rnow<r){
    24         rnow++;
    25         sumr[rnow]=gcd(sumr[rnow-1],a[rnow]);
    26         if(sumr[rnow]!=sumr[rnow-1])
    27             dlr[++dlr[0]]=rnow-1;
    28     }
    29     dlr[++dlr[0]]=r;
    30     for(ll lh=1;lh<=dll[0];lh++)
    31         for(ll rh=1;rh<=dlr[0];rh++){
    32             ll nowl=dll[lh],nowr=dlr[rh];
    33             ll g=gcd(suml[nowl],sumr[nowr]);
    34 //            printf("nowl=%lld nowr=%lld =%lld
    ",dll[lh],dlr[rh],g*(nowr-nowl+1));
    35             if(g==1) break;
    36             ans=max(ans,g*(nowr-nowl+1));
    37         }
    38     ans=max(ans,gcd(suml[l],sumr[r])*(r-l+1));
    39     solve(l,mid);solve(mid+1,r);
    40 }
    41 //10 10 101 10 10 
    42 int main(){
    43 //    freopen("da.in","r",stdin);
    44 //    freopen("ans.sol","w",stdout);
    45     scanf("%lld",&n);
    46     for(ll i=1;i<=n;i++){
    47         scanf("%lld",&a[i]);
    48     }
    49     solve(1,n);
    50     printf("%lld
    ",ans);
    51 }
    View Code

    E

    这个题真的很迷

    题解

     垃圾zzn考试时打的第二个贪心,然后只有$60$分,事实上单纯第一个贪心就可以$100$分,数据特别水,第一个贪心明明连样例都过不去

    没遇到数据这么水的,

    正确性垃圾zzn当然不会验证啦

    代码也懒的放了

    F

    题解

    0分算法

    直接暴力$dp$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 ll f[2][2019][2019],w[2019];
     5 ll a,b,n,q;
     6 int main(){
     7     scanf("%lld%lld%lld%lld",&n,&q,&a,&b);
     8     memset(f,0x7f,sizeof(f));
     9     for(ll i=1;i<=q;i++)
    10         scanf("%lld",&w[i]);
    11     f[1][a][w[1]]=abs(b-w[1]);
    12     f[1][w[1]][b]=abs(a-w[1]);
    13     for(ll i=2;i<=q;i++){
    14         memset(f[i&1],0x7f,sizeof(f[i&1]));
    15         for(ll j=1;j<=n;j++){
    16         f[i&1][j][w[i]]=min(f[i&1][j][w[i]],f[(i-1)&1][j][w[i-1]]+abs(w[i]-w[i-1]));//w[i-1]移动到w[i]
    17         f[i&1][w[i]][w[i-1]]=min(f[i&1][w[i]][w[i-1]],f[(i-1)&1][j][w[i-1]]+abs(j-w[i]));//j移动到w[i]
    18         f[i&1][w[i]][j]=min(f[i&1][w[i]][j],f[(i-1)&1][w[i-1]][j]+abs(w[i]-w[i-1]));//w[i-1]移动到w[i]
    19         f[i&1][w[i-1]][w[i]]=min(f[i&1][w[i-1]][w[i]],f[(i-1)&1][w[i-1]][j]+abs(j-w[i]));//j移动到w[i]
    20         }
    21     }
    22     ll ans=0x7fffffff;
    23     for(ll j=1;j<=n;j++){
    24         ans=min(ans,min(f[q&1][j][w[q]],f[q&1][w[q]][j]));
    25     }
    26     printf("%lld
    ",ans);
    27 }
    View Code

    30分算法

    有一维一定是$w[i]$

    考虑去掉一维

    $f[i][j]=f[i-1][j]+abs(w[i]-w[i-1])$另一个指针从$w[i-1]$移动到$w[i]$

    $f[i][w[i-1]]=f[i-1][j]+abs(j-w[i])$从$j$移动到$w[i]$

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll f[2][2019],w[2019];
    ll a,b,n,q;
    int main(){
        scanf("%lld%lld%lld%lld",&n,&q,&a,&b);
        memset(f,0x7f,sizeof(f));
        for(ll i=1;i<=q;i++)
            scanf("%lld",&w[i]);
        f[1][a]=abs(b-w[1]);
        f[1][b]=abs(a-w[1]);
        for(ll i=2;i<=q;i++){
            memset(f[i&1],0x7f,sizeof(f[i&1]));
            for(ll j=1;j<=n;j++){
            f[i&1][j]=min(f[i&1][j],f[(i-1)&1][j]+abs(w[i]-w[i-1]));
            f[i&1][w[i-1]]=min(f[i&1][w[i-1]],f[(i-1)&1][j]+abs(j-w[i]));
            f[i&1][j]=min(f[i&1][j],f[(i-1)&1][j]+abs(w[i]-w[i-1]));
            f[i&1][w[i-1]]=min(f[i&1][w[i-1]],f[(i-1)&1][j]+abs(j-w[i]));
            }
        }
        ll ans=0x7fffffff;
        for(ll j=1;j<=n;j++){
            ans=min(ans,min(f[q&1][j],f[q&1][j]));
        }
        printf("%lld
    ",ans);
    }
    View Code

    100分算法

    两个转移式子

    $f[i][j]=f[i-1][j]+abs(w[i]-w[i-1])$

    $f[i][w[i-1]]=f[i-1][j]+abs(j-w[i])$

    发现第一个式子就是区间加,第二个式子单点赋值

    单点赋值赋的就是$min$,有个$abs$怎么办维护$f-j$最小值和$f+j$最小值

            memset(askmin,0x7f,sizeof(askmin));
            seg_min(1,1,w[i],2);//p[i]比当前点大,那么取p[i]-l
            seg_min(1,w[i],n,1);//p[i]比当前值小,取l-p[i]
        //    printf("ask=%lld %lld
    ",askmin[1],askmin[2]);
            askmin[1]-=w[i];
            askmin[2]+=w[i];
            ll nowmin=min(askmin[1],askmin[2]);

    线段树优化一下

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 ll w[1010101],askmin[4];
     5 ll a,b,n,q;
     6 struct tree{
     7     ll l,r,f,minn[4];
     8 }tr[1010101];
     9 void up(ll x){
    10     for(ll i=1;i<=3;i++)
    11         tr[x].minn[i]=min(tr[x<<1].minn[i],tr[x<<1|1].minn[i]);
    12 }
    13 void down(ll x){
    14     tr[x<<1].f+=tr[x].f;
    15     tr[x<<1|1].f+=tr[x].f;
    16     for(ll i=1;i<=3;i++)
    17         tr[x<<1].minn[i]+=tr[x].f,tr[x<<1|1].minn[i]+=tr[x].f;
    18     tr[x].f=0;
    19 }
    20 void built(ll x,ll l,ll r){//printf("builx=%lld
    ",x);
    21     tr[x].l=l,tr[x].r=r;
    22     if(l==r){
    23         if(l==a||l==b){
    24             tr[x].minn[3]=abs(a+b-l-w[1]);
    25 //            printf("tr3=%lld
    ",tr[x].minn[3]);
    26             tr[x].minn[1]=tr[x].minn[3]+l;
    27             tr[x].minn[2]=tr[x].minn[3]-l;
    28         }
    29         else tr[x].minn[1]=tr[x].minn[2]=tr[x].minn[3]=0x7ffffffffff;
    30         return ;
    31     }
    32     ll mid=(l+r)>>1;
    33     built(x<<1,l,mid);
    34     built(x<<1|1,mid+1,r);
    35     up(x);
    36 }
    37 void seg_min(ll x,ll l,ll r,ll zl){
    38 //    printf("l=%lld r=%lld
    ",l,r);
    39     if(tr[x].l>=l&&tr[x].r<=r){
    40 //        printf("tr[%lld].minn[%lld]=%lld l=%lld r=%lld
    ",x,zl,tr[x].minn[zl],tr[x].l,tr[x].r);
    41         askmin[zl]=min(askmin[zl],tr[x].minn[zl]);
    42         return ;
    43     }
    44     down(x);
    45     ll mid=(tr[x].l+tr[x].r)>>1;
    46     if(mid>=l) seg_min(x<<1,l,r,zl);
    47     if(mid<r) seg_min(x<<1|1,l,r,zl);
    48     up(x);
    49 }
    50 void add(ll x,ll point,ll val){
    51     if(tr[x].l==tr[x].r){
    52         tr[x].minn[3]=min(tr[x].minn[3],val);
    53         tr[x].minn[1]=tr[x].minn[3]+tr[x].l;
    54         tr[x].minn[2]=tr[x].minn[3]-tr[x].l;
    55         return ;
    56     }
    57     down(x);
    58     ll mid=(tr[x].l+tr[x].r)>>1;
    59     if(point<=mid) add(x<<1,point,val);
    60     else add(x<<1|1,point,val);
    61     up(x);
    62 }
    63 int main(){
    64     scanf("%lld%lld%lld%lld",&n,&q,&a,&b);
    65     for(ll i=1;i<=q;i++)
    66         scanf("%lld",&w[i]);
    67     built(1,1,n);
    68     for(ll i=2;i<=q;i++){
    69         memset(askmin,0x7f,sizeof(askmin));
    70         seg_min(1,1,w[i],2);//p[i]比当前点大,那么取p[i]-l
    71         seg_min(1,w[i],n,1);//p[i]比当前值小,取l-p[i]
    72     //    printf("ask=%lld %lld
    ",askmin[1],askmin[2]);
    73         askmin[1]-=w[i];
    74         askmin[2]+=w[i];
    75         ll nowmin=min(askmin[1],askmin[2]);
    76     //    printf("nowmin=%lld
    ",nowmin);
    77         tr[1].f+=abs(w[i]-w[i-1]);
    78         for(ll j=1;j<=3;j++)
    79             tr[1].minn[j]+=abs(w[i]-w[i-1]);
    80         add(1,w[i-1],nowmin);
    81     }
    82     printf("%lld
    ",tr[1].minn[3]);
    83 }
    View Code
  • 相关阅读:
    html问题记录20180529
    html问题记录20180518
    html问题记录20180515
    Redis持久化--AOF
    Redis持久化--RDB
    Redis事件模型
    两个字符串的编辑距离-动态规划方法
    Reactor事件模型在Redis中的应用
    事件驱动模式--Reactor
    IO多路复用--总结
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11535091.html
Copyright © 2011-2022 走看看