• BZOJ NOIP提高组十连测第一场


    今天的题目一共拿了$180$分,感觉自己还是太菜了,二三两题只能骗到部分分

    1、$String Master$

    题目大意:有两个字符串,在允许k次失配的情况下,求最长公共子串的长度

    没什么好讲,直接一个$O(n^3)$的解法就过了,数据范围很小,枚举公共子串在两个字符串的起点,在大于当前字符串长度或在大于$k$次失配后退出,更新答案。

    话说卡常后拿了全站$rank1$

    $Code Below:$

    #include <bits/stdc++.h>
    using namespace std;
    int max(int a,int b){return a>b?a:b;}
    
    int main()
    {
    	register int n,k,ans=0;
    	char s[310],t[310];
        scanf("%d%d
    ",&n,&k);
        scanf("%s",s);
        scanf("%s",t);
        for(register int i=0;i<n;i++)
            for(register int j=0;j<n;j++){
                register int l,cur=0;
                for(l=1;i+l<=n&&j+l<=n;l++){
                    cur+=(s[i+l-1]!=t[j+l-1]);
                    if(cur>k) break;
                }
                ans=max(ans,--l);
            }
        printf("%d
    ",ans);
        return 0;
    }
    

      

    我的得分:$100$

    2、$Tourist Attraction$

    题目大意:给定点数为$n$的无向图,求经过不重复的$a-b-c-d$的简单路径

    $40$分做法:直接深搜

    $70$分做法:枚举每一条边的$b-c$,然后$a,d$个数就可以用每个点的度数计算出来,所以$b-c$这条边对答案的贡献为$(dg[a]-1)*(dg[d]-1)$**(想想为什么减一?因为要除去b和c啊)**并减去环的个数
    而环的个数恰恰是$70$分解法的瓶颈

    $100$分做法:对于$70$分做法,定义所有边终点为$i$的起点集合为$S_i$,其实环的个数就是$card(S_acap S_d)$,所以$STL$中冷门数据结构$bitset$就登场了。交集的个数就是两者做与操作后位上$1$的个数

    时间复杂度:$O(m*n/32)$

    $Code Below:$

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn=1500+10;
    ll n,dg[maxn],edgex[maxn*maxn],edgey[maxn*maxn],tot,ans;
    char s[maxn];
    bitset<maxn> t,sum[maxn];
    
    int main()
    {
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		getchar();getchar();
    		for(ll j=1;j<=n;j++){
    			scanf("%c",&s[j]);
    			if(s[j]=='1'){
    				sum[i][j]=1;
    				edgex[++tot]=i,edgey[tot]=j;
    				dg[j]++;
    			}
    		}
    	}
    	for(ll i=1;i<=tot;i++){
    		ll x=edgex[i],y=edgey[i];
    		ans+=(dg[x]-1)*(dg[y]-1);
    		t=sum[x]&sum[y];
    		ans-=(ll)t.count();
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }

    趁这个机会学了一下$bitset$

    我的得分:$40$

    3、$Walk$

    题目大意:

    $40$分做法:直接$BFS$跑最短路

    $Code Below:$

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,val[130010<<1],head[1300010<<1],fir[1300010<<1],cnt=1<<20,tot,dis[1300010<<1];
    struct node {
    	int to,next,val;
    } e[1300010<<1];
    queue<int> q;
    
    inline void add(int x,int y,int w) {
    	e[++tot].to=y;
    	e[tot].val=w;
    	e[tot].next=head[x];
    	head[x]=tot;
    }
    inline void add1(int x,int y,int w) {
    	e[++tot].to=y;
    	e[tot].val=w;
    	e[tot].next=fir[x];
    	fir[x]=tot;
    }
    void add_point(int x,int dep)
    {
    	if(dis[x]!=-1) return;
    	dis[x]=dep;q.push(x);
    	for(int i=head[x];i;i=e[i].next)
    		add_point(e[i].to,dep);
    	if(x<=cnt){
    		for(int i=0;i<=20;i++)
    			if(x&(1<<i)) add_point(x^(1<<i),dep);
    	}
    }
    int main() 
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&val[i]);
    		add(val[i],i+cnt,0);
    		add1(i+cnt,val[i],1);
    	}
    	for(int i=1;i<=m;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		if(x!=y) add1(x+cnt,y+cnt,1);
    	}
    	memset(dis,-1,sizeof(dis));
    	dis[1+cnt]=0;
    	while(!q.empty()) q.pop();
    	memset(dis,-1,sizeof(dis));
    	dis[1+cnt]=0;q.push(1+cnt);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=fir[u];i;i=e[i].next){
    			if(dis[e[i].to]==-1){
    				q.push(e[i].to);
    				add_point(e[i].to,dis[u]+1);
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    		printf("%d
    ",dis[i+cnt]);
    	return 0;
    }
    

      

    我的得分:$40$

    总结:在攻难题的同时,保证水题正确率$100$%

  • 相关阅读:
    Luogu P2495 [SDOI2011]消耗战
    40. Combination Sum II
    39. Combination Sum
    22. Generate Parentheses
    51. N-Queens
    Codeforces Round #346 (Div. 2) E. New Reform
    Codeforces Round #346 (Div. 2) D. Bicycle Race
    HDU 5651xiaoxin juju needs help
    VK Cup 2016
    Educational Codeforces Round 10 D. Nested Segments
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/9503831.html
Copyright © 2020-2023  润新知