zoukankan      html  css  js  c++  java
  • Petrozavodsk Winter-2018. Jagiellonian U Contest

    A. XOR

    求出所有数的异或和$sum$,将所有数and上$sum$,然后求线性基,则选取$sum$的所有$1$对应的基最优。

    时间复杂度$O(nlog x)$。

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    int Case,n,i,j;ll ans,sum,A,B,a[100],x,v[111111],pool[100];
    const int N=20;
    ll cal(){
    	ll ans=sum;
    	for(int S=0;S<1<<n;S++){
    		ll A=sum,B=0;
    		for(i=0;i<n;i++)if(S>>i&1)A^=v[i],B^=v[i];
    		A-=B;
    		if(A<0)A=-A;
    		if(A<ans)ans=A;
    	}
    	return ans;
    }
    void print(ll x){
    	for(int i=11;~i;i--)printf("%lld",x>>i&1);
    	puts("");
    }
    ll myabs(ll x){return x>0?x:-x;}
    ll solve1(int x){
    	ll cur=a[x];
    	for(int i=x-1;~i;i--)if(sum>>i&1){
    		cur^=a[i];
    	}
    	return myabs(cur-(sum^cur));
    }
    ll solve2(int x){
    	ll cur=0;
    	for(int i=x-1;~i;i--){
    		cur=max(cur,cur^a[i]);
    	}
    	return myabs(cur-(sum^cur));
    }
    int main(){
    	//srand(time(NULL));
    	scanf("%d",&Case);
    	while(Case--){
    		scanf("%d",&n);
    		//n=rand()%10+1;
    		sum=0;
    		for(i=0;i<61;i++)a[i]=0;
    		for(i=0;i<n;i++){
    			scanf("%lld",&x);
    			//x=rand()%1000;
    			v[i]=x;
    			sum^=x;
    			for(j=60;~j;j--)if(x>>j&1){
    				if(a[j])x^=a[j];
    				else {a[j]=x;break;}
    			}
    		}
    		
    		//ll vio=cal();
    		
    		for(i=0;i<61;i++)for(j=i+1;j<61;j++)if(a[j]>>i&1)a[j]^=a[i];
    		
    		for(i=60;~i;i--)if(sum>>i&1)break;
    		int lim=i;
    		if(lim>=0){
    			for(i=0;i<61;i++)pool[i]=a[i]&sum,a[i]=0;
    			for(i=0;i<61;i++){
    				x=pool[i];
    				for(j=60;~j;j--)if(x>>j&1){
    					if(a[j])x^=a[j];
    					else {a[j]=x;break;}
    				}
    			}
    			for(i=0;i<61;i++)for(j=i+1;j<61;j++)if(a[j]>>i&1)a[j]^=a[i];
    			ans=min(sum,min(solve1(lim),solve2(lim)));
    		}else{
    			ans=0;
    		}
    		
    		/*A=sum,B=0;*/
    		
    		//print(sum);
    		//for(i=60;~i;i--)if(a[i])print(a[i]);
    		
    		/*ans=sum;
    		for(i=60;~i;i--)if((A^a[i])>=(B^a[i])&&(A^a[i])-(B^a[i])<ans){
    			A^=a[i];
    			B^=a[i];
    			ans=A-B;
    		}*/
    		/*if(ans==vio)puts("OK");else{
    			printf("vio=%lld ans=%lld
    ",vio,ans);
    			printf("%d
    ",n);
    			for(i=0;i<n;i++)printf("%lld ",v[i]);
    			puts("");
    			while(1);
    		}*/
    		printf("%lld
    ",ans);
    	}
    }
    

      

    B. Tribute

    按题意模拟即可。

    #include<bits/stdc++.h>
    using namespace std;
    int casenum, casei;
    typedef unsigned int UI;
    int n;
    vector<UI>vt, wt;
    multiset<UI>sot;
    multiset<UI>ans;
    bool solve()
    {
    	for(int i = 1; i <= n; ++i)
    	{
    		int x = *sot.begin();
    		ans.insert(x);
    //		printf("x = %d
    ", x);
    //		for(auto y : vt)printf("%d ", y); puts("");
    		wt.clear();
    		for(auto y : vt)
    		{
    			int z = x + y;
    //			printf("%d
    ", z);
    			if(sot.find(z) == sot.end())return 0;
    			sot.erase(sot.find(z));
    			wt.push_back(z);
    		}
    		for(auto y : wt)vt.push_back(y);
    	}
    	return 1;
    }
    int main()
    {
    	scanf("%d", &casenum);
    	for(casei = 1; casei <= casenum; casei ++)
    	{
    		scanf("%d", &n);
    		int m = (1 << n) - 1;
    		vt.clear(); vt.push_back(0);
    		sot.clear();
    		ans.clear();
    		for(int i = 1; i <= m; ++i)
    		{
    			int x; scanf("%d", &x);
    			sot.insert(x);
    		}
    		if(!solve())puts("NO");
    		else
    		{
    			int id = 0;
    			for(auto it : ans)printf("%d%c", it, ++id == n ? '
    ' : ' ');
    		}
    	}
    }
    

      

    C. Boardroom Meeting

    CDQ分治+扫描线树状数组,时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=200010;
    int Case,n,i,a[N],b[N],c[N],ans,f[N],qa[N],qb[N],bit[N],vis[N],T;
    inline void up(int&a,int b){a<b?(a=b):0;}
    inline void ins(int x,int p){for(;x<=n;x+=x&-x)if(vis[x]<T)vis[x]=T,bit[x]=p;else up(bit[x],p);}
    inline void ask(int x,int&p){for(;x;x-=x&-x)if(vis[x]==T)up(p,bit[x]);}
    inline bool cmp(int x,int y){return a[x]<a[y];}
    void solve(int l,int r){
    	if(l==r){
    		up(ans,++f[l]);
    		return;
    	}
    	int mid=(l+r)>>1,i,j,ca=0,cb=0;
    	solve(l,mid);
    	for(i=l;i<=mid;i++)qa[++ca]=i;
    	for(;i<=r;i++)qb[++cb]=i;
    	sort(qa+1,qa+ca+1,cmp);
    	sort(qb+1,qb+cb+1,cmp);
    	T++;
    	for(i=j=1;i<=cb;i++){
    		while(j<=ca&&a[qa[j]]<a[qb[i]]){
    			ins(b[qa[j]],f[qa[j]]);
    			j++;
    		}
    		ask(b[qb[i]]-1,f[qb[i]]);
    	}
    	solve(mid+1,r);
    }
    int main(){
    	scanf("%d",&Case);
    	while(Case--){
    		scanf("%d",&n);
    		for(i=1;i<=n;i++)scanf("%d",&a[i]);
    		for(i=1;i<=n;i++)scanf("%d",&b[i]),c[i]=b[i];
    		sort(c+1,c+n+1);
    		for(i=1;i<=n;i++)b[i]=lower_bound(c+1,c+n+1,b[i])-c;
    		for(i=1;i<=n;i++)f[i]=0;
    		ans=0;
    		solve(1,n);
    		printf("%d
    ",ans);
    	}
    }
    /*
    1
    6
    1 2 6 3 4 6
    4 1 3 5 7 7
    */
    

      

    D. Secret Santa

    第二类斯特林数容斥,时间复杂度$O(alog n)$。

    #include<cstdio>
    const int N=2010,P=1000000007;
    int n,a,i,j,Case,fac[N],S[N][N];
    int po(int a,int b){int t=1;for(;b;b>>=1,a=1LL*a*a%P)if(b&1)t=1LL*t*a%P;return t;}
    int T(int m,int n){
      int ans=0;
      for(int k=0;k<m;k++){
        int t=fac[k];
        if((k+m)%2)t=(P-t)%P;
        t=1LL*t*po(k+1,n)%P;
        t=1LL*t*S[m][k+2]%P;
        ans=(ans+t)%P;
      }
      return ans;
    }
    int main(){
      for(i=0;i<N;i++)for(j=0;j<N;j++){
        if(i>=1&&j==0){S[i][j]=0;continue;}
        if(i==j){S[i][j]=1;continue;}
        if(j>=1&&j<i)S[i][j]=(1LL*S[i-1][j]*j+S[i-1][j-1])%P;
      }
      for(fac[0]=i=1;i<N;i++)fac[i]=1LL*fac[i-1]*i%P;
      scanf("%d",&Case);
      while(Case--){
        scanf("%d%d",&n,&a);a++;n-=a-2;
        printf("%d
    ",T(a,n));
      }
    }
    

      

    E. Guessing Game

    状压DP,设$f[S]$表示$S$情况下最优策略最坏需要的步数,其中$S$是个$k$位$3$进制数,分别表示每一位未询问、已询问且回答为$0$、已询问且回答为$1$的情况。

    用高维前缀和预处理出所有$f[S]=0$的状态,剩下的状态枚举询问哪一位转移即可。

    时间复杂度$O(3^kk)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=13,M=1600000;
    int p[20],Case,n,m,i,j,k,f[M],c[M];char s[20];
    inline int get(int x,int y){return x/p[y]%3;}
    int main(){
    	for(p[0]=i=1;i<20;i++)p[i]=p[i-1]*3;
    	scanf("%d",&Case);
    	while(Case--){
    		scanf("%d%d",&n,&k);
    		m=p[k];
    		for(i=0;i<m;i++)c[i]=0;
    		for(i=1;i<=n;i++){
    			scanf("%s",s);
    			int t=0;
    			for(j=0;j<k;j++)t=t*3+s[j]-'0';
    			c[t]++;
    		}
    		for(i=0;i<k;i++)for(j=0;j<m;j++)if(get(j,i)==2){
    			c[j]+=c[j-p[i]]+c[j-p[i]*2];
    		}
    		for(i=0;i<m;i++){
    			if(c[i]<=1){f[i]=0;continue;}
    			f[i]=M;
    			for(j=0;j<k;j++)if(get(i,j)==2){
    				f[i]=min(f[i],max(f[i-p[j]],f[i-p[j]*2]));
    			}
    			f[i]++;
    		}
    		printf("%d
    ",f[m-1]);
    	}
    }
    

      

    F. Flat Earth

    按题意模拟即可。

    #include<stdio.h>
    #include<math.h>
    
    int casenum, casei, a[10];
    const double PI = acos(-1.0);
    
    int main()
    {
    	scanf("%d", &casenum);
    	for(casei = 1; casei <= casenum; casei ++){
    		for(int i = 1; i <= 8; i ++){
    			scanf("%d", &a[i]);
    		}
    		printf("%.10f
    ", PI * a[4] * a[4]);
    	}
    }
    

      

    G. We Need More Managers!

    建立一张$2^n$个点的图,分别表示每种串。对于每个点,向恰好改变了一位的$n$个点连边。

    则题意可转化为对给定$m$个点求出两两最短路作为权值的最小生成树。

    设$p_x$和$d_x$分别表示离每个点最近的给定串以及对应的距离,可以BFS求出,则对于一条边$(u,v)$,在生成树中加入一条连接$p_u$和$p_v$,权值为$d_u+d_v+1$的边即可。

    时间复杂度$O(n2^nalpha(m))$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=1100000;
    int Case,n,m,all,i,j,a[N];char s[100];
    int h,t,d[N],p[N],x,y,z,q[N];
    int f[N],ans,ce;
    struct E{
    	int x,y,z;
    	E(){}
    	E(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
    }e[N*20];
    inline bool cmp(const E&a,const E&b){return a.z<b.z;}
    inline void ext(int x,int y,int z){
    	if(y<d[x]){
    		d[x]=y;
    		p[x]=z;
    		q[++t]=x;
    	}
    }
    int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
    inline void add(int x,int y,int z){
    	if(x!=y)e[++ce]=E(x,y,z);
    }
    int main(){
    	scanf("%d",&Case);
    	while(Case--){
    		scanf("%d%d",&n,&m);
    		all=1<<n;
    		for(i=0;i<all;i++)d[i]=N;
    		for(i=1;i<=m;i++){
    			scanf("%s",s);
    			a[i]=0;
    			for(j=0;j<n;j++)a[i]=a[i]*2+(s[j]=='L');
    			d[a[i]]=0,p[a[i]]=i;
    		}
    		h=1,t=0;
    		for(i=0;i<all;i++)if(!d[i])q[++t]=i;
    		while(h<=t){
    			x=q[h++];
    			y=d[x]+1;
    			z=p[x];
    			for(i=0;i<n;i++)ext(x^(1<<i),y,z);
    		}
    		ce=0;
    		for(i=0;i<all;i++)for(j=0;j<n;j++)add(p[i],p[i^(1<<j)],d[i]+d[i^(1<<j)]+1);
    		for(i=1;i<=m;i++)f[i]=i;
    		ans=0;
    		sort(e+1,e+ce+1,cmp);
    		for(i=1;i<=ce;i++)if(F(e[i].x)!=F(e[i].y))f[f[e[i].x]]=f[e[i].y],ans+=e[i].z;
    		printf("%d
    ",ans);
    	}
    }
    

      

    H. Masterpiece

    若不考虑每个点是被第几次走过的,则方案唯一,$O(n)$模拟求出方案后统计分岔点个数$t$,则答案为$2^t$。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    void fre() {  }
    #define MS(x, y) memset(x, y, sizeof(x))
    #define rt 1,1,n
    #define ls o<<1
    #define rs o<<1|1
    #define mid (l+r>>1)
    #define lson ls,l,mid
    #define rson rs,mid+1,r
    typedef long long LL;
    typedef unsigned long long UL;
    typedef unsigned int UI;
    template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
    template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
    const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
    template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
    int casenum, casei;
    int n;
    int r[N], c[N];
    //try go to (y, x)
    bool flag = 1;
    int r1, r2;
    int c1, c2;
    bool doit(int y, int x)
    {
        if(r1 == r2 && c1 == c2)return flag = 1;
        if(y > n || x > n)return 0;
        if(!r[y] || ! c[x])return 0;
        --r[y];
        --c[x];
        return flag = 1;
    }
    int solve()
    {
        int ans = 1;
        r1 = 1, c1 = 1;
        r2 = 1, c2 = 1;
        doit(1, 1); --r[1]; --c[1];
        while(1)
        {
            flag = 0;
            if(r1 == r2 && c1 == c2)
            {
                if(r1 == n && c1 == n)
                {
                    return ans;
                }
                int rnum = r[r1];
                int cnum = c[c1];
                if(rnum && cnum)
                {
                    ans = ans * 2 % Z;
                    for(int i = 1; i <= rnum; ++i)
                    {
                        if(!doit(r1, ++c1))return 0;
                    }
                    for(int i = 1; i <= cnum; ++i)
                    {
                        if(!doit(++r2, c2))return 0;
                    }
                }
                else if(rnum)
                {
                    if(!doit(r1, ++c1))return 0;
                    ++c2;
                }
                else if(cnum)
                {
                    if(!doit(++r1, c1))return 0;
                    ++r2;
                }
                else return 0;
            }
            while(r1 < r2)
            {
                if(r[r1])
                {
                    if(!doit(r1, ++c1))return 0;
                }
                else
                    if(!doit(++r1, c1))return 0;
            }
            while(r2 < r1)
            {
                if(r[r2])
                {
                    if(!doit(r2, ++c2))return 0;
                }
                else
                    if(!doit(++r2, c2))return 0;
            }
            while(c1 < c2)
            {
                if(c[c1])
                {
                    if(!doit(++r1, c1))return 0;
                }
                else
                    if(!doit(r1, ++c1))return 0;
            }
            while(c2 < c1)
            {
                if(c[c2])
                {
                    if(!doit(++r2, c2))return 0;
                }
                else
                    if(!doit(r2, ++c2))return 0;
            }
            if(!flag)return 0;
        }
    }
    int main()
    {
    	scanf("%d", &casenum);
    	for(casei = 1; casei <= casenum; ++casei)
    	{
            scanf("%d", &n);
            //int n = rand() % 10 + 1;
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d", &r[i]);
                //r[i] = rand() % (n + 1);
            }
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d", &c[i]);
                //c[i] = rand() % (n + 1);
            }
            int ans = solve();
            for(int i = 1; i <= n; ++i)
            {
                if(r[i] || c[i])ans = 0;
            }
            printf("%d
    ", ans);
    	}
    	return 0;
    }
    
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    100
    5
    3 3 3 3 3
    1 4 4 3 3
    
    4
    4 2 2 4
    4 2 2 4
    
    */
    

      

    I. Don’t Split The Atom!

    胜负只取决于$n$的奇偶性。

    #include<stdio.h>
    #include<math.h>
    
    int casenum, casei, a[10];
    const double PI = acos(-1.0);
    
    int main()
    {
    	scanf("%d", &casenum);
    	for(casei = 1; casei <= casenum; casei ++){
    		int n;
    		scanf("%d", &n);
    		puts(n & 1 ? "B" : "A");
    	}
    }
    

      

    J. Bobby Tables

    组合数可以看作长度为$k$的一个区间除以长度为$k$的一个前缀。

    枚举每个$k$作为前缀,二分对应的区间,取对数加速判定,在附近配合取模判定即可。

    时间复杂度$O(mlog m)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long double ld;
    const int N=200010,P=1000000007,K=20;
    const ld eps=1e-2;
    int Case,n,m,i,a[N],fac[N],inv[N],mul;
    ld Log[N],s[N],sum;
    inline bool check(int n,int m){
    	ld A=s[n]-s[n-m]-s[m];
    	if(fabs(A-sum)>eps)return 0;
    	int B=1LL*fac[n]*inv[n-m]%P*inv[m]%P;
    	if(B!=mul)return 0;
    	puts("YES");
    	printf("%d %d
    ",n,m);
    	return 1;
    }
    inline void solve(){
    	scanf("%d%d",&n,&m);
    	sum=0;
    	mul=1;
    	for(i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		mul=1LL*mul*a[i]%P;
    		sum+=Log[a[i]];
    	}
    	for(i=1;i<=m;i++){
    		//[x,x+i-1]/[1..i]
    		//C(x+i-1,i)
    		//x+i-1>=i
    		//1<=x<=m+1-i
    		//x+i-1<=m
    		int l=1,r=m+1-i;
    		while(l<=r){
    			int mid=(l+r)>>1;
    			ld A=s[mid+i-1]-s[mid-1]-s[i];
    			if(fabs(A-sum)<eps){
    				for(int j=max(mid-K,1);j<=min(m+1-i,mid+K);j++)if(check(j+i-1,i))return;
    				break;
    			}
    			if(A<sum)l=mid+1;else r=mid-1;
    		}
    	}
    	puts("NO");
    }
    int main(){
    	for(i=1;i<N;i++)Log[i]=log2(i);
    	for(i=1;i<N;i++)s[i]=s[i-1]+Log[i];
    	for(inv[0]=inv[1]=1,i=2;i<N;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P;
    	for(fac[0]=i=1;i<N;i++)fac[i]=1LL*fac[i-1]*i%P;
    	for(i=1;i<N;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
    	scanf("%d",&Case);
    	while(Case--){
    		solve();
    	}
    }
    

      

    K. Triples

    长链剖分或树分治经典题。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #define pb push_back
    #define V vector
    #define N 200010
    using namespace std;
    typedef long long ll;
    typedef pair<int,ll>P;
    int Case;
    int n,i,x,y,g[N],v[N<<1],nxt[N<<1],ed,f[N],del[N];ll ans;V<P>h[N];
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline bool cmp(V<int>*a,V<int>*b){return a->size()>b->size();}
    template<class C>inline C&get(V<C>&a,size_t x){return a[a.size()-x-1];}
    V<int>*dfs(int x,int y){
      V<V<int>*>t;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y)t.pb(dfs(v[i],x));
      if(!t.size())return new V<int>(1,1);
      sort(t.begin(),t.end(),cmp);
      V<int>*a=t[0];
      a->pb(1);
      if(t.size()==1)return a;
      V<ll>b;
      b.resize(t[1]->size()+1,0);
      for(int i=1;i<t.size();i++){
        V<int>*u=t[i];
        for(int j=1;j<=u->size();j++){
          int ch=get(*u,j-1),&rt=get(*a,j);ll&rd=get(b,j);
          ans+=1LL*ch*rd;
          rd+=1LL*ch*rt;
          rt+=ch;
        }
      }
      for(int i=1;i<b.size();i++){
        h[x].pb(P(i,get(b,i)));
        ans-=1LL*get(b,i)*get(*a,i);
      }
      return a;
    }
    void cal(int x,int y){
      f[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&!del[v[i]])cal(v[i],x),f[x]+=f[v[i]];
    }
    inline int findroot(int x){
      cal(x,-1);
      int n=f[x],t=0,y=-1;
      do{
        t=0;
        for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&!del[v[i]]&&2*f[v[i]]>n){
          y=x,x=v[i],t=1;
          break;
        }
      }while(t);
      return x;
    }
    inline void work(V<V<int> >&d,V<V<P> >&q,int k,bool rt,int x){
      int st=k==1?0:d.size()-1,en=k==1?d.size():-1;V<int>a(1,rt); 
      for(int i=st;i!=en;i+=k){
        V<int>D=d[i];
        for(V<P>::iterator p=q[i].begin();p!=q[i].end();p++){
          int j=p->first;
          if(j<a.size())ans+=1LL*a[j]*p->second;
        }
        a.resize(max(a.size(),D.size()),0);
        for(int j=0;j<D.size();j++)a[j]+=D[j];
      }
      if(rt)for(V<P>::iterator p=h[x].begin();p<h[x].end();p++){
        int j=p->first;
        if(j<a.size())ans+=1LL*a[j]*p->second;
      }
    }
    void dfsd(int x,int y,int z,V<int>&d){
      if(z==d.size())d.pb(1);else d[z]++;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&!del[v[i]])dfsd(v[i],x,z+1,d);
    }
    void dfsq(int x,int y,int z,V<P>&q){
      for(V<P>::iterator i=h[x].begin();i<h[x].end();i++){
        int t=i->first-z;
        if(t>=0)q.pb(P(t,i->second));
      }
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&!del[v[i]])dfsq(v[i],x,z+1,q);
    }
    void solve(int x){
      int y=findroot(x);
      del[y]=1;
      for(int i=g[y];i;i=nxt[i])if(!del[v[i]])solve(v[i]);
      V<V<int> >d;V<V<P> >q;
      for(int i=g[y];i;i=nxt[i])if(!del[v[i]]){
        V<int>A(1,0);
        dfsd(v[i],-1,1,A);
        d.pb(A);
        V<P>B;
        dfsq(v[i],-1,1,B);
        q.pb(B);
      }
      work(d,q,1,1,y),work(d,q,-1,0,y);
      del[y]=0;
    }
    int main(){
      scanf("%d",&Case);
      while(Case--){
        i=x=y=0;
        memset(g,0,sizeof g);
        memset(f,0,sizeof f);
        memset(v,0,sizeof v);
        memset(nxt,0,sizeof nxt);
        ed=0;
        memset(del,0,sizeof del);
        ans=0;
        for(i=0;i<N;i++)h[i].clear();
        scanf("%d",&n);
        for(i=1;i<n;i++){
          scanf("%d%d",&x,&y);
          x--,y--;
          add(x,y),add(y,x);
        }
        dfs(0,-1);
        solve(0);
        printf("%lld
    ",ans);
      }
    }
    

      

    L. Related Languages

    枚举$O(nm)$对区间右端点,左端点的取值满足单调性,双指针即可。

    时间复杂度$O(nm)$。

    #include<cstdio>
    const int N=4010;
    int Case,n,m,i,j,k,ans,g[N*3];
    char a[N],b[N],f[N][N];
    int w[N*3],V;
    int main(){
      scanf("%d",&Case);
      while(Case--){
        scanf("%d%d%d%s%s",&n,&m,&V,a+1,b+1);
        ans=0;
        for(i=1;i<=n;i++)for(j=1;j<=m;j++)f[i][j]=a[i]!=b[j];
        for(i=0;i<=N+N+5;i++)g[i]=w[i]=0;
        for(i=1;i<=n;i++)for(j=1;j<=m;j++){
          k=i-j+N;
          g[k]++;
          w[k]+=f[i][j];
          int G=g[k],W=w[k];
          while(G>0&&W>V){
            G--;
            W-=f[i-G][j-G];
          }
          g[k]=G;
          w[k]=W;
          if(G>ans)ans=G;
        }
        printf("%d
    ",ans);
      }
    }
    

      

  • 相关阅读:
    [国家集训队] Crash 的文明世界
    [国家集训队] middle
    [正睿集训2021] 构造专练
    [正睿集训2021] LIS
    CF482E ELCA
    UVA
    UVA
    UVA
    UVA
    UVA
  • 原文地址:https://www.cnblogs.com/clrs97/p/8519422.html
Copyright © 2011-2022 走看看