• Educational Codeforces Round 60 (Div.2)


    A.找到最大值x,再找出最长的连续的x。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=100010;
    10 int n,tot,mx,ans,a[N];
    11 
    12 int main(){
    13     scanf("%d",&n);
    14     rep(i,1,n) scanf("%d",&a[i]),mx=max(mx,a[i]);
    15     rep(i,1,n) if (a[i]==mx) tot++; else ans=max(ans,tot),tot=0;
    16     printf("%d
    ",max(ans,tot));
    17     return 0;
    18 }
    A

    B.连续k个最大值后跟1个次大值,如此循环。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=400010;
    10 int n,m,k,a[N];
    11 
    12 int main(){
    13     scanf("%d%d%d",&n,&m,&k);
    14     rep(i,1,n) scanf("%d",&a[i]);
    15     sort(a+1,a+n+1);
    16     int s=m/(k+1),p=m%(k+1);
    17     cout<<1ll*s*(1ll*k*a[n]+a[n-1])+1ll*p*a[n]<<endl;
    18     return 0;
    19 }
    B

    C.二分答案,根据风向向量和与目标距离之间的曼哈顿距离判断是否可行。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=200010;
    10 char op;
    11 int n;
    12 ll x1,y1,x2,y2;
    13 struct P{ ll x,y; }p[N];
    14 
    15 int main(){
    16     cin>>x1>>y1>>x2>>y2>>n; x2-=x1; y2-=y1;
    17     p[0]=(P){0,0};
    18     rep(i,1,n){
    19         scanf(" %c",&op); p[i]=p[i-1];
    20         if (op=='U') p[i].y++;
    21         if (op=='D') p[i].y--;
    22         if (op=='L') p[i].x--;
    23         if (op=='R') p[i].x++;
    24     }
    25     ll L=1,R=1e15;
    26     while (L<R){
    27         ll mid=(L+R)>>1,x=(mid/n)*p[n].x+p[mid%n].x,y=(mid/n)*p[n].y+p[mid%n].y;
    28         if (abs(x2-x)+abs(y2-y)<=mid) R=mid; else L=mid+1;
    29     }
    30     if (L>1e14) puts("-1"); else cout<<L<<endl;
    31     return 0;
    32 }
    C

    D.f[n]=f[n-1]+f[n-m],矩阵快速幂优化。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=110,mod=1e9+7;
    10 ll n;
    11 int m;
    12 
    13 struct Mat{ int a[N][N]; Mat(){memset(a,0,sizeof(a));} }ans;
    14 
    15 Mat operator *(const Mat &a,const Mat &b){
    16     Mat c;
    17     rep(i,1,m) rep(j,1,m) rep(k,1,m) c.a[i][k]=(c.a[i][k]+1ll*a.a[i][j]*b.a[j][k])%mod;
    18     return c;
    19 }
    20 
    21 Mat ksm(ll n){
    22     Mat res,a;
    23     rep(i,1,m) a.a[i+1][i]=1,res.a[i][i]=1;
    24     a.a[1][m]=1; a.a[m][m]=1;
    25     for (; n; a=a*a,n>>=1)
    26         if (n & 1) res=res*a;
    27     return res;
    28 }
    29 
    30 int main(){
    31     cin>>n>>m;
    32     if (n<m){ puts("1"); return 0; }
    33     rep(i,1,m-1) ans.a[1][i]=1; ans.a[1][m]=2;
    34     ans=ans*ksm(n-m);
    35     cout<<ans.a[1][m]<<endl;
    36     return 0;
    37 }
    D

    E.26*26*26>10000,确定置换后每个位置的26进制(即将x表示为a*26^2+b*26+c,三次询问分别确定a,b,c)。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int N=10010;
     8 int n;
     9 char s[N],q[3][N],g[3][N],ans[N];
    10 
    11 int main(){
    12     scanf("%s",s); n=strlen(s);
    13     rep(i,0,n-1){
    14         q[0][i]=(i/(26*26)%26+'a');
    15         q[1][i]=(i/26%26+'a');
    16         q[2][i]=(i%26+'a');
    17     }
    18     rep(i,0,2) printf("? %s
    ",q[i]),fflush(stdout),scanf("%s",g[i]);
    19     rep(i,0,n-1){
    20         int tmp=(g[0][i]-'a')*26*26+(g[1][i]-'a')*26+(g[2][i]-'a');
    21         ans[tmp]=s[i];
    22     }
    23     printf("! %s",ans);
    24     return 0; 
    25 }
    E

    F.一个自然的想法是,用二进制压位S表示留下某些字母后这个串是否合法,权值设为串长,然后从11..1开始BFS找到权值最小的点即可。

    考虑如何判断一个S是否合法,一个暴力的想法是枚举i,j,然后O(n)判定是否存在某对i,j之间的所有字符都被删去。

    但这样复杂度是$O(n2^pp^2)$的,考虑用i,j来筛S。

    枚举i,j,考虑原串中每对i,j,如果S在i+1~j-1上的每种字符上都为0,那么这个S就是不合法的。

    在考虑每对i,j时,这样的S是一个高维前缀。于是打标记,然后做一个高维后缀和就可以知道每个S在考虑i,j两种字母时是否合法了。

    于是复杂度为枚举i,j并打标记的$O(np^2)$+对每个不合法i,j做高维后缀和的$O(2^pp^3)$+对每个S枚举i,j判断是否合法的$O(2^pp^2)$+从11..1开始BFS的$O(2^p)$,也就是$O(2^pp^3)$。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 using namespace std;
     5 
     6 const int N=300010,K=18;
     7 char s[N];
     8 bool sm[K*K][N],b[N],vis[N];
     9 int n,p,tot,ans,ss,w[K][K],mp[K][K],a[N],cnt[K],q[N];
    10 
    11 int cal(int S){ int res=0; rep(i,1,p) if (S&(1<<(i-1))) res+=cnt[i]; return res; }
    12 
    13 void work(int x,int y,int k){
    14     int tot=0;
    15     rep(i,1,n) if (s[i]-'a'+1==x || s[i]-'a'+1==y) a[++tot]=i;
    16     rep(i,1,tot-1) if ((s[a[i]]-'a'+1==x && s[a[i+1]]-'a'+1==y) || (s[a[i]]-'a'+1==y && s[a[i+1]]-'a'+1==x)){
    17         int S=0;
    18         rep(j,a[i]+1,a[i+1]-1) S|=1<<(s[j]-'a');
    19         S^=ss; sm[k][S]=1;
    20     }
    21 }
    22 
    23 int main(){
    24     scanf("%d%d%s",&n,&p,s+1); ans=n+1; ss=(1<<p)-1;
    25     rep(i,1,n) cnt[s[i]-'a'+1]++;
    26     rep(i,1,p) rep(j,1,p) scanf("%d",&mp[i][j]);
    27     rep(i,1,p) rep(j,i,p) if (!mp[i][j]) w[i][j]=++tot,work(i,j,tot);
    28     rep(x,1,tot){
    29         for (int i=1; i<=ss; i<<=1)
    30             rep(j,1,ss) if (j&i) sm[x][j^i]|=sm[x][j];
    31     }
    32     rep(S,0,ss){
    33         b[S]=1;
    34         rep(i,1,p) rep(j,i,p)
    35             if (S&(1<<(i-1)) && S&(1<<(j-1)) && !mp[i][j] && sm[w[i][j]][S]){ b[S]=0; break; }
    36     }
    37     q[1]=ss; vis[ss]=1;
    38     for (int st=0,ed=1; st!=ed; ){
    39         int S=q[++st]; ans=min(ans,cal(S));
    40         rep(i,1,p){
    41             int S1=S^(1<<(i-1));
    42             if (S&(1<<(i-1)) && !vis[S1] && b[S1]) vis[S1]=1,q[++ed]=S1;
    43         }
    44     }
    45     printf("%d
    ",ans);
    46     return 0;
    47 }
    F

    G.令$fl(l,r)=(m_{l,r}-l)+fl(l,m_{l,r}-1)+fl(m_{l,r}+1,r)$,$fr(l,r)$同理,那么$f(l,r)=fl(l,r)+fr(l,r)+(r-l+1)$,于是考虑求$fr$即可,$fl$类似。

    发现对于一个i来说,它对$fr$的贡献等于它到下一个比它大的数的距离(或询问右端点)。

    对操作离线,i从小到大枚举,线段树维护当考虑位置1~i的数时,每个询问右端点的答案。

    对于一个位置i,它对询问右端点r的贡献是$min(nxt[i]-i-1,r-i)$,这是一个一次函数后加一个常数函数。

    线段树内用kx+b来表示一个数即可,打标记是时直接斜率和截距相加。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define ls (x<<1)
     6 #define rs (ls|1)
     7 #define lson ls,L,mid
     8 #define rson rs,mid+1,R
     9 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
    10 typedef long long ll;
    11 using namespace std;
    12 
    13 const int N=1000010;
    14 ll ans[N],tag1[N<<2],tag2[N<<2];
    15 int n,m,a[N],stk[N],nxt[N];
    16 struct P{ int l,r,id; ll ans; }q[N];
    17 bool operator <(const P &a,const P &b){ return a.l<b.l; }
    18 
    19 void build(int x,int L,int R){
    20     if (L==R){ tag1[x]=tag2[x]=0; return; }
    21     int mid=(L+R)>>1; build(lson); build(rson);
    22 }
    23 
    24 void push(int x){
    25     if (tag1[x]) tag1[ls]+=tag1[x],tag1[rs]+=tag1[x],tag1[x]=0;
    26     if (tag2[x]) tag2[ls]+=tag2[x],tag2[rs]+=tag2[x],tag2[x]=0;
    27 }
    28 
    29 void mdf(int x,int L,int R,int l,int r,int k,int b){
    30     if (L==l && r==R){ tag1[x]+=k; tag2[x]+=b; return; }
    31     int mid=(L+R)>>1; push(x);
    32     if (r<=mid) mdf(lson,l,r,k,b);
    33     else if (l>mid) mdf(rson,l,r,k,b);
    34         else mdf(lson,l,mid,k,b),mdf(rson,mid+1,r,k,b);
    35 }
    36 
    37 ll que(int x,int L,int R,int k){
    38     if (L==R) return tag1[x]*k+tag2[x];
    39     int mid=(L+R)>>1; push(x);
    40     if (k<=mid) return que(lson,k); else return que(rson,k);
    41 }
    42 
    43 void solve(){
    44     int top=1; stk[1]=n+1; a[n+1]=n+1;
    45     for (int i=n; i; i--){
    46         while (top && a[stk[top]]<a[i]) top--;
    47         nxt[i]=stk[top]; stk[++top]=i;
    48     }
    49     sort(q+1,q+m+1); int r=0; build(1,1,n);
    50     rep(i,1,n){
    51         while (r<m && q[r+1].l==i) r++,q[r].ans-=que(1,1,n,q[r].r);
    52         mdf(1,1,n,i,nxt[i]-1,1,-i);
    53         if (nxt[i]<=n) mdf(1,1,n,nxt[i],n,0,nxt[i]-i-1);
    54     }
    55     rep(i,1,m) q[i].ans+=que(1,1,n,q[i].r);
    56 }
    57 
    58 int main(){
    59     freopen("g.in","r",stdin);
    60     freopen("g.out","w",stdout);
    61     scanf("%d%d",&n,&m);
    62     rep(i,1,n) scanf("%d",&a[i]);
    63     rep(i,1,m) scanf("%d",&q[i].l),q[i].id=i;
    64     rep(i,1,m) scanf("%d",&q[i].r),q[i].ans=q[i].r-q[i].l+1;
    65     solve();
    66     reverse(a+1,a+n+1);
    67     rep(i,1,m) q[i].l=n-q[i].l+1,q[i].r=n-q[i].r+1,swap(q[i].l,q[i].r);
    68     solve();
    69     rep(i,1,m) ans[q[i].id]=q[i].ans;
    70     rep(i,1,m) cout<<ans[i]<<' ';
    71     return 0;
    72 }
    G
  • 相关阅读:
    寻找我的黑客偶像
    20201215 《信息安全专业导论》第三周学习总结
    罗马数字
    base编码
    20201215 王馨瑶 第2周学习总结
    罗马数字转阿拉伯数字
    2020-2021-1 20201226 《信息安全专业导论》第三周学习总结
    IEEE754 浮点数
    Base64
    2020-2021-1 20201226 《信息安全专业导论》第2周学习总结
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10718907.html
Copyright © 2020-2023  润新知