zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    手机号码正则表达式
    POJ 3233 Matrix Power Series 矩阵快速幂
    UVA 11468
    UVA 1449
    HDU 2896 病毒侵袭 AC自动机
    HDU 3065 病毒侵袭持续中 AC自动机
    HDU 2222 Keywords Search AC自动机
    POJ 3461 Oulipo KMP模板题
    POJ 1226 Substrings KMP
    UVA 1455 Kingdom 线段树+并查集
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10718907.html
Copyright © 2011-2022 走看看