1. 程式人生 > >1.11考試

1.11考試

author 還要 inf 表示 ont 有時 stdout 子結構 strlen

歷經千百爆零

總算茍上了200

多虧題水,痛失AK

T1:隨便貪心即可。解封之後,棧裏可能連續彈出要註意。

T2:

技術分享圖片

技術分享圖片

區間dp既視感

直接dp答案不好搞,最優子結構基本沒有。。

考慮求cos[l][r]表示刪掉l,r花費,

枚舉用哪個刪

因為一段一段,所以,還要考慮留下的前綴

g[l][r][id][len],[l,r]開始,刪到留下第id個串前len位的最小花費

愉快dp

cos完了後,f[i][j]前i位,刪了j次留下的最小長度

O(n^3*m*len)必須剪枝

發現,cos[l][r]很大程度上是inf,或者比k大,

所以g的轉移的時候,把cos循環到外面,如果cos[s+1][j]大於k-1,直接continue

穩穩AC

技術分享圖片
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^‘0‘)
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch==-)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10
+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=202; const int inf=0x3f3f3f3f; int n,m,k; char a[N]; char b[N][N]; int f[N][N]; int len[N]; namespace sol1{ int nxt[N]; void main(){ int ans=n; for(reg i=1;i<=m;++i){ int l=strlen(b[i]+1); for(reg j=1;j<=n-l+1
;++j){ int p=j,t=1; while(t<=l&&b[i][t]==a[p]) ++t,++p; if(t>l) ans=min(ans,n-l); } } printf("%d",ans); } } namespace sol2{ int cos[N][N]; int g[N][N][22][13]; void main(){ memset(cos,inf,sizeof cos); memset(g,inf,sizeof g); for(reg i=1;i<=n;++i){ for(reg j=1;j<=m;++j){ if(len[j]==1&&b[j][1]==a[i]) { cos[i][i]=1; g[i][i][j][len[j]]=0; g[i][i][j][0]=1; } if(b[j][1]==a[i]){ g[i][i][j][1]=0; } } cos[i][i-1]=0; }cos[n+1][n]=0; for(reg i=1;i<=n;++i){ for(reg p=1;p<=m;++p){ g[i][i-1][p][0]=0; } } //cout<<" seee "<<endl; for(reg l=2;l<=n;++l){ for(reg i=1;i<=n;++i){ int j=i+l-1; if(j>n) break; for(reg s=i;s<=j;++s){ cos[i][j]=min(cos[i][j],cos[i][s]+cos[s+1][j]); } for(reg p=1;p<=m;++p)g[i][i-1][p][0]=0; for(reg s=i-1;s<j;++s){ if(s!=i-1&&cos[s+1][j]>k-1) continue; for(reg p=1;p<=m;++p){ // for(reg o=0;o<=len[p];++o){ g[i][j][p][o]=g[i][j][p][o]>g[i][s][p][o]+cos[s+1][j]?g[i][s][p][o]+cos[s+1][j]:g[i][j][p][o]; if(o>=1&&b[p][o]==a[j]) g[i][j][p][o]=min(g[i][j][p][o],g[i][j-1][p][o-1]); } //cos[i][j]=min(cos[i][j],g[i][j][p][len[p]]+1); } } for(reg p=1;p<=m;++p){ cos[i][j]=min(cos[i][j],g[i][j][p][len[p]]+1); } } } // for(reg l=1;l<=n;++l){ // for(reg i=1;i<=n;++i){ // int j=i+l-1; // if(j>n) break; // cout<<" i j "<<i<<" "<<j<<" : "<<cos[i][j]<<endl; // } // } int ans=inf; if(cos[1][n]<=k){ ans=cos[1][n]; printf("%d\n",ans);return; } memset(f,inf,sizeof f); f[0][0]=0; for(reg i=1;i<=n;++i){ for(reg j=0;j<=k;++j){ if(j>0){ for(reg p=0;p<i;++p){ if(cos[p+1][i]<=j) f[i][j]=min(f[i][j],f[p][j-cos[p+1][i]]); } } for(reg p=0;p<i;++p){ if(cos[p+1][i-1]<=j) f[i][j]=min(f[i][j],f[p][j-cos[p+1][i-1]]+1); } } } for(reg l=0;l<=k;++l){ ans=min(ans,f[n][l]); } printf("%d ",ans); } } int main(){ rd(n);rd(m);rd(k); scanf("%s",a+1); for(reg i=1;i<=m;++i){ scanf("%s",b[i]+1); len[i]=strlen(b[i]+1); } if(k==1){ sol1::main(); return 0; }else{ sol2::main(); } return 0; } } signed main(){ // freopen("string.in","r",stdin); // freopen("string.out","w",stdout); Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/1/11 11:26:10 */
View Code

本來思路和正解一毛一樣

但是以為沒有優化空間

g數組每次暴力求的,,其實記錄一下用[l,r]就可以少求n次,砍掉1維

然後加上剪枝即可。

以為O(n^3*m*len)過不去,,,

T3:

[SDOI2014]向量集

的弱化版

技術分享圖片

線段樹維護凸包即可。

(可能腦殘沒有推出這個斜率優化的式子,,考慮點積的意義搞的右上凸包,,,當凸包斜率最接近-x/y時最大)

技術分享圖片
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define mid ((l+r)>>1)
#define numb (ch^‘0‘)
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch==-)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=300000+5;
int n;
struct po{
    int x,y;
    po(){}
    po(int xx,int yy){
        x=xx;y=yy;
    }
    bool friend operator <(po a,po b){
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    po friend operator -(po a,po b){
        return po(a.x-b.x,a.y-b.y);
    }
};
int cross(po a,po b){
    return a.x*b.y-b.x*a.y;
}
int dot(po a,po b){
    return a.x*b.x+a.y*b.y;
}
bool con(po a,po b){
    return (a.x>=b.x)&&(a.y>=b.y);
}

struct node{
    vector<po>mem;
}t[4*N];
void upda(int x,po c){
//    cout<<" udpa "<<x<<" : "<<c.x<<" "<<c.y<<" "<<t[x].mem.size()<<endl;
    if(t[x].mem.size()==0) t[x].mem.push_back(c);
    else if(t[x].mem.size()==1){
        if(con(c,t[x].mem[0])) {
            t[x].mem.pop_back();
        }
        t[x].mem.push_back(c);
    }
    else{
        while(t[x].mem.size()>1){
            int sz=t[x].mem.size();
            int tmp=cross(t[x].mem[sz-1]-c,t[x].mem[sz-2]-c);
            //cout<<" tmp "<<tmp<<endl;
            if(tmp<=0) t[x].mem.pop_back();
            else break;
        }
        t[x].mem.push_back(c);
    }
}
void pushup(int x){
//    cout<<" pushup "<<x<<endl;
    int ls=x<<1,rs=x<<1|1;
    int l=0,r=0;
    int sz=t[ls].mem.size()+t[rs].mem.size();
    //cout<<" sz "<<sz<<endl;
    for(reg i=1;i<=sz;++i){
        //cout<<" num i "<<i<<endl;
        if(l==(int)t[ls].mem.size()){
            //cout<<" case 1"<<endl;
            upda(x,t[rs].mem[r]);++r;
        }else if(r==(int)t[rs].mem.size()){
            //cout<<" case 2"<<endl;
            upda(x,t[ls].mem[l]);++l;
        }else if(t[ls].mem[l]<t[rs].mem[r]){
            //cout<<" case 3"<<endl;
            upda(x,t[ls].mem[l]);++l;
        }else{
            //cout<<" case 4"<<endl;
            upda(x,t[rs].mem[r]);++r;
        }
    }
    //cout<<" szzzzz "<<t[x].mem.size()<<endl;
}
void ins(int x,int l,int r,int p,po c){
    if(l==r){
    //    cout<<" got "<<l<<" "<<r<<endl;
        t[x].mem.push_back(c);
        return;
    }
    if(p<=mid) ins(x<<1,l,mid,p,c);
    else ins(x<<1|1,mid+1,r,p,c);
    //cout<<" bac to "<<x<<" p "<<p<<" l r "<<l<<" "<<r<<endl;
    if(p==r) pushup(x);
//    cout<<" ret "<<endl;
}
int query(int x,int l,int r,int L,int R,po c){
    if(L<=l&&r<=R){
        //cout<<" xx "<<x<<" "<<l<<" "<<r<<" "<<t[x].mem.size()<<endl;
        int ll=0,rr=t[x].mem.size()-1;//warning!!!! -1
        int id=0; 
        while(ll<=rr){
            int md=(ll+rr)>>1;
            if(md==0){
                id=0;break;
            }else{
                if((t[x].mem[md].y-t[x].mem[md-1].y)*c.y>=(t[x].mem[md-1].x-t[x].mem[md].x)*c.x){
                    id=md;ll=md+1;
                }else{
                    rr=md-1;
                }
            }
        }
        int ret=0;
        //cout<<" idid "<<id<<endl;
        if(id>=0) ret=max(ret,dot(c,t[x].mem[id]));
        if(id>=1) ret=max(ret,dot(c,t[x].mem[id-1]));
        if(id<(int)t[x].mem.size()-1) ret=max(ret,dot(c,t[x].mem[id+1]));
        return ret;
    }
    int ret=0;
    if(L<=mid) ret=max(ret,query(x<<1,l,mid,L,R,c));
    if(mid<R) ret=max(ret,query(x<<1|1,mid+1,r,L,R,c));
    return ret;
}
int main(){
    rd(n);
    int op;
    int las=0;
    int x,y,l,r;
    int now=0;
    for(reg i=1;i<=n;++i){
        rd(op);
        if(op==1){
            rd(x);rd(y);
            x^=las;y^=las;
            ++now;
            //cout<<" op1 "<<x<<" "<<y<<endl;
            //p[++now].x=x;p[now].y=y;
            ins(1,1,n,now,po(x,y));
        //    cout<<" ksdjf "<<endl;
        }else{
            rd(x);rd(y);rd(l);rd(r);
            x^=las;y^=las;l^=las;r^=las;
            int ans=query(1,1,n,l,r,po(x,y));
            las=ans;
            printf("%d\n",ans);
        }
    }
    return 0;
}

}
signed main(){
//    freopen("vector.in","r",stdin);
//    freopen("vector.out","w",stdout);
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/1/11 9:33:04
*/
View Code

總結:
很懸

T2還是不夠老練,,這種trick,多積累吧 。而且暴力打的不夠果斷。還是應該想不出來直接打暴力。差點沒有時間

T3斜率優化沒有推出來?害的考慮半天幾何意義開始還錯了。

1.11考試