zoukankan      html  css  js  c++  java
  • 20190919

    A1

    DP (O(n^3))
    其实不用枚举从谁开始跳。。。懒得改了

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=51;
    struct node { int c,h;
      inline bool operator < (const node& that) const {return h>that.h;}
    }a[N];
    int n,m,ans,f[N][N],d[N];
    inline void main() {
      n=g(); for(R i=1;i<=n;++i) a[i].c=g();
      for(R i=1;i<=n;++i) a[i].h=g(); m=g();
      sort(a+1,a+n+1);
      for(R t=1;t<=n;++t) if(a[t].c<=m) { 
        memset(f,0x3f,sizeof f),f[t][1]=a[t].c,ans=max(ans,1);
        memset(d,0x3f,sizeof d),d[1]=a[t].c+a[t].h; 
        for(R i=t+1;i<=n;++i) {
          for(R j=i-t+1;j>=1;--j) {
            f[i][j]=d[j-1]-a[i].h+a[i].c;
            if(f[i][j]<=m) ans=max(ans,j);
            if(d[j]>f[i][j]+a[i].h) d[j]=f[i][j]+a[i].h;
          }
        }
      } printf("%d
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    A2

    排好序后显然第一项是 (a_1+a_2),第二项是 (a_1+a_3),我们可以枚举 (a_2+a_3) ,然后显然除了前面的三项,此时最小是 (a_1+a_4),这时我们标记 (a_2+a_4) , (a_3+a_4),此时没有被标记中的最小的是 (a_1+a_5)。。。以此类推。
    复杂度不到 (O(n^3log(n)))

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int M=45000,N=301;
    int n,m,cnt,mem[N],ans[N][N],a[M];
    bool vis[M];
    inline void ck(int p) {//枚举x2+x3 
      memset(vis,0,sizeof vis);
      if((a[1]+a[2]+a[p])&1) return ;//若是奇数,显然不能等于2*(x1+x2+x3)
      mem[1]=(a[1]+a[2]+a[p])/2-a[p]; 
      mem[2]=a[1]-mem[1],mem[3]=a[2]-mem[1];
      vis[1]=vis[2]=vis[p]=true;
      for(R p=4,q=3;p<=n;++p) { 
        while(q<=m&&vis[q]) ++q;
        if(q>m) return ; mem[p]=a[q]-mem[1]; vis[q]=true;
        for(R i=2;i<p;++i) { //检查解是否合法 
          if(mem[i]>mem[p]) return ; //有序
          R vl=mem[i]+mem[p]; R pos=lower_bound(a+1,a+m+1,vl)-a;
          if(a[pos]!=vl) return ;//没有对应的数 
          R tmp=pos; while(tmp<=m&&a[tmp]==a[pos]&&vis[tmp]) ++tmp;//找到最靠前且没有用过的
          if(a[tmp]!=a[pos]||vis[tmp]) return ;//有对应的数但是都用过
          pos=tmp,vis[pos]=true; 
        }
      } ++cnt; for(R i=1;i<=n;++i) ans[cnt][i]=mem[i]; 
    }
    inline void main() {
      n=g(),m=n*(n-1)/2; for(R i=1;i<=m;++i) a[i]=g();
      sort(a+1,a+m+1); for(R p=3;p<=m;) {
        ck(p); R q=p; while(q<=m&&a[p]==a[q]) ++q; p=q;//跳过一样的数 
      } printf("%d
    ",cnt);
      for(R i=1;i<=cnt;++i,puts("")) for(R j=1;j<=n;++j) printf("%d ",ans[i][j]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    A3

    套路,可是我不会。
    把询问离线,看作两个前缀和相减;
    考虑如何平衡修改与查询的复杂度,我们可以每次花 (O(100)) 处理出一个数对 (pleq 100)时的答案,查询时直接使用答案。
    (p > 100) ,他的倍数很少,我们可以直接查 (k*p+v) 出现了几次(之前开个桶)。

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    namespace Fread {
    static char B[1<<15],*S=B,*T=B;
    #define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } 
    } using Fread::g;
    const int N=100010,L=10000,B=100;
    struct node { int p,v,id; bool op; node() {}
      node(int _p,int _v,int _id,bool _op) {p=_p,v=_v,id=_id,op=_op;}
    }vr[N<<1]; int n,m,a[N];
    int cnt,s[L+10],c[B+10][B+10],nxt[N<<1],fir[N],ans[N][2];
    inline void main() {
      n=g(),m=g(); for(R i=1;i<=n;++i) a[i]=g();
      for(R i=1;i<=m;++i) {
        R l=g(),r=g(),p=g(),v=g();
        vr[++cnt]=node(p,v,i,0),nxt[cnt]=fir[l-1],fir[l-1]=cnt;
        vr[++cnt]=node(p,v,i,1),nxt[cnt]=fir[r],fir[r]=cnt;
      } for(R u=1;u<=n;++u) { ++s[a[u]];
        for(R i=1;i<=B;++i) ++c[i][a[u]%i];
        for(R i=fir[u];i;i=nxt[i]) { R p=vr[i].p,v=vr[i].v;
          if(p<=B) ans[vr[i].id][vr[i].op]=c[p][v];
          else { R tmp=0;
            for(R i=v;i<=L;i+=p) tmp+=s[i];
            ans[vr[i].id][vr[i].op]=tmp;
          }
        }
      } for(R i=1;i<=m;++i) printf("%d
    ",ans[i][1]-ans[i][0]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    B1 我菜爆了 100pts

    我打表才看出来DP(递推)式子。。。
    实际上可以理解为在上一个序列的最前面依次插了(1,2,3cdots n),他会与后面的 (n-1) 项产生 (0,1,2cdots n-1) 个逆序对
    所以 (f[n][k]) 可以继承 (sum_{max(0,k-n+1)leq ileq k}f[n-1][i])

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=1000,M=10000;
    int T,n,k;
    int f[N+10][N+10],s[N+10][N+10];
    inline void main() {
      f[1][0]=s[1][0]=s[1][1]=s[1][2]=1;
      for(R i=2;i<=N;++i) { 
        for(R j=0,lim=min(i*(i-1)/2,N);j<=lim;++j) {
          if(j-i>=0) f[i][j]=((s[i-1][j]-s[i-1][j-i])%M+M)%M;
          else f[i][j]=s[i-1][j];
        } s[i][0]=1;
        for(R j=1,lim=min(i*(i+1)/2,N);j<=lim;++j) 
          s[i][j]=(s[i][j-1]+f[i][j])%M;
      } T=g(); while(T--) {
        n=g(),k=g(); printf("%d
    ",(f[n][k]%M+M)%M);
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    B2 我被爆踩了 0pts

    ST表两维写反(为什要用ST表)
    还用了对顶堆的 (n^2logn) 的做法(并不用对顶堆,直接每个数向两边扫一下 (n^2) 就够了)
    菜的真实。

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int LEN=200,N=2010;
    struct node { int p,w; node() {} node(int _p,int _w) {p=_p,w=_w;}
      inline bool operator < (const node& that) const {return w<that.w||(w==that.w&&p<that.p);}
      inline bool operator > (const node& that) const {return w>that.w||(w==that.w&&p>that.p);}
    }; 
    priority_queue<node> p;
    priority_queue<node,vector<node>,greater<node> > q;
    int n,m,a[N],s[N],mx[12][N],lg[N];
    inline void build() {
      lg[1]=0; for(R i=2;i<=n;++i) lg[i]=lg[i>>1]+1; memcpy(mx[0],s,sizeof s);
      for(R t=1,lim=lg[n];t<=lim;++t) for(R i=1,lim=n-(1<<t)+1;i<=lim;++i) 
        mx[t][i]=max(mx[t-1][i],mx[t-1][i+(1<<t-1)]);
    }
    inline int qmx(int l,int r) {R t=lg[r-l+1]; return max(mx[t][l],mx[t][r-(1<<t)+1]);}
    inline void main() {
      n=g(); for(R i=1;i<=n;++i) a[i]=g(); for(R i=1;i<=n;++i) {
        while(p.size()) p.pop(); while(q.size()) q.pop();
        for(R j=i;j<=n;j+=2) {
          p.push(node(j,a[j])); if(j-i) p.push(node(j-1,a[j-1])); register node tmp;
          while(p.size()>(j-i+2)/2) tmp=p.top(),p.pop(),q.push(tmp);
          if(q.size()&&p.top()>q.top()) {
            register node t=p.top(); tmp=q.top();
            p.pop(),q.pop(); p.push(tmp),q.push(t);
          } R pos=p.top().p; s[pos]=max(s[pos],j-i+1);
        }
      } build(); m=g(); while(m--) {
        R l=g(),r=g(); printf("%d
    ",qmx(l,r));
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    B3 又是套路但是我不会

    缺乏总结。。
    我们又要平衡复杂度。
    我们定义 (f[A][B]) 为 二进制表示下 前8位位(A) 的子集,后8位为 (B) 的数的个数。
    添加时枚举超集,查询时枚举子集。

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const short N=1<<8,L=8,B=N-1;
    int c[N+1][N+1],n;
    inline void main() {
      n=g(); for(R i=1;i<=n;++i) { register char ch; 
        while(!isalpha(ch=getchar())); 
        R x=g(); if(ch=='a') { register short tmp=x&B,b=x>>L;
          for(register short i=x>>L;i<N;i=b|(i+1)) ++c[i][tmp];
        } if(ch=='d') { register short tmp=x&B,b=x>>L;;
          for(register short i=x>>L;i<N;i=b|(i+1)) --c[i][tmp];
        } if(ch=='c') { R ans=0; register short tmp=(x>>L)&B,b=x&B;
          for(register short i=x&B;i;i=b&(i-1)) {
            ans+=c[tmp][i]; 
          } ans+=c[tmp][0]; printf("%d
    ",ans);
        }
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    总结

    做的题挺多,却不总结
    一定改。

  • 相关阅读:
    SparkSQL & Spark on Hive & Hive on Spark
    Elasticsearch和Scala类型转换
    Java和Scala容器转换
    Spark应用远程调试
    scala下划线的用法
    Maven打包方式
    安装ElasticSearch遇到的深坑
    SparkSQL JDBC和JDBCServer区别
    source命令用法:source FileName
    System.getProperty()
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11567926.html
Copyright © 2011-2022 走看看