zoukankan      html  css  js  c++  java
  • [CLYZ2017]day17

    三元组

    image

    solution

    60分

    \(s[i]\)表示以\(i\)结尾的回文串的首项下标和.
    \(t[i]\)表示以\(i\)开头的回文串的末项下标和.
    答案为\(sum_{i=1}^{|S|-1}s[i]\times{t[i+1]}\).
    \(manacher\)求出以每个点为中心的最长回文串半径,此回文串范围内对\(s[\;],t[\;]\)区间覆盖等差数列.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 2000005
    #define M 1000000007
    using namespace std;
    int r[N<<1],s[N],t[N],n,ti,ans;
    char a[N<<1];
    inline void add_s(int l,int r,int m){
    	for(int i=l;i<=r;++i)
    		s[i]+=m-i;
    }
    inline void add_t(int l,int r,int m){
    	for(int i=l;i<=r;++i)
    		t[i]+=m-i;
    }
    inline void manacher(){
    	int mx=0,id=0;
    	m=n=strlen(a+1);
    	for(int i=n;i;--i){
    		a[i<<1]=a[i];a[i<<1|1]='#';
    	}
    	n=n<<1|1;
    	a[0]='$';a[1]='#';
    	for(int i=1;i<=n;++i){
    		r[i]=i<mx?min(r[(id<<1)-i],mx-i):1;
    		while(a[i+r[i]]==a[i-r[i]]) ++r[i];
    		if(i+r[i]>mx) mx=i+r[i],id=i;
    		add_s(i+1>>1,(i>>1)+(r[i]-1>>1),i);
    		add_t((i+1>>1)-(r[i]-1>>1),i>>1,i); 
    	}
    }
    inline void Aireen(){
    	scanf("%d",&ti);
    	while(ti--){
    		scanf("%s",a+1);
    		n=strlen(a+1);
    		memset(s,0,sizeof(s));
    		memset(t,0,sizeof(t));
    		manacher();
    		ans=0ll;
    		for(int i=2;i<=n;++i){
    			ans+=1ll*s[i-1]*t[i]%M;
    			if(ans>M) ans-=M;
    		}
    		printf("%d\n",ans);
    	}
    }
    
    int main(){
    	freopen("triple.in","r",stdin);
    	freopen("triple.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    100分

    利用差分的思想\(O(1)\)覆盖等差数列,统计的时候计算前缀和即可.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 1000005
    #define M 1000000007
    using namespace std;
    int r[N<<1],s[N],t[N],ks[N],kt[N],n,m,ti,ans;
    char a[N<<1];
    inline void add_s(int l,int r,int m){
    	if(l>r) return;
    	s[l]+=m-l;s[r+1]-=m-r;
    	if(s[l]>M) s[l]-=M;
    	if(s[r+1]<-M) s[r+1]+=M; 
    	--ks[l+1];++ks[r+1];
    }
    inline void add_t(int l,int r,int m){
    	if(l>r) return;
    	t[l]+=m-l;t[r+1]-=m-r;
    	if(t[l]>M) t[l]-=M;
    	if(t[r+1]<-M) t[r+1]+=M; 
    	--kt[l+1];++kt[r+1];
    }
    inline void manacher(){
    	int mx=0,id=0;
    	m=n=strlen(a+1);
    	for(int i=n;i;--i){
    		a[i<<1]=a[i];a[i<<1|1]='#';
    	}
    	n=n<<1|1;
    	a[0]='$';a[1]='#';
    	for(int i=1;i<=n;++i){
    		r[i]=i<mx?min(r[(id<<1)-i],mx-i):1;
    		while(a[i+r[i]]==a[i-r[i]]) ++r[i];
    		if(i+r[i]>mx) mx=i+r[i],id=i;
    		add_s(i+1>>1,(i>>1)+(r[i]-1>>1),i);
    		add_t((i+1>>1)-(r[i]-1>>1),i>>1,i); 
    	}
    }
    inline void Aireen(){
    	scanf("%d",&ti);
    	while(ti--){
    		scanf("%s",a+1);
    		memset(s,0,sizeof(s));
    		memset(t,0,sizeof(t));
    		memset(ks,0,sizeof(ks));
    		memset(kt,0,sizeof(kt));
    		manacher();ans=0ll;
    		for(int i=1,k1=0,k2=0;i<=m;++i){
    			k1+=ks[i];
    			s[i]+=s[i-1]+k1;
    			if(s[i]>M) s[i]-=M;
    			k2+=kt[i];
    			t[i]+=t[i-1]+k2;
    			if(t[i]>M) t[i]-=M;
    		}
    		for(int i=2;i<=m;++i){
    			ans+=1ll*s[i-1]*t[i]%M;
    			if(ans>M) ans-=M;
    		}
    		printf("%d\n",ans);
    	}
    }
    int main(){
    	freopen("triple.in","r",stdin);
    	freopen("triple.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    最优价值

    image

    solution

    最大权闭合子图

    对于边\((u,v)\),如果选择\(u\),必须选择\(v\).

    建图

    对于原图中的边\((u,v)\),连边\((u,v)=+\infty\).
    如果点\(u\)\(w\)为正,连边\((s,u)=w\);否则连边\((u,t)=-w\).
    \(w_{max}=\sum_{w_i>0}{w_i}-Mincut\)

    100分

    分为三类点:\((i,j)=w(i,j),i=-a,x=-b_x+a_x\).
    \((i,j)\)连向\(i,j;i\)连向\(s[i]\).
    用最大权闭合子图做即可.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define K 110
    #define N 100000
    #define M 1000000
    #define INF 1000000000
    #define min(a,b) (a<b?a:b)
    using namespace std;
    struct graph{
    	int nxt,to,f;
    }e[M];
    int w[K][K],p[K][K],c[K],a[10],b[10],g[N],dep[N],n,m,k,s,t,cnt,sum;
    char ch[K];
    queue<int> q;
    inline void addedge(int x,int y,int f){
    	e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].f=f;
    } 
    inline void adde(int x,int y,int f){
    	addedge(x,y,f);addedge(y,x,0);
    }
    inline bool bfs(int u){
    	memset(dep,0,sizeof(dep));
    	dep[u]=1;q.push(u);
    	while(!q.empty()){
    		u=q.front();q.pop();
    		for(int i=g[u];i;i=e[i].nxt)
    			if(e[i].f>0&&!dep[e[i].to]){
    				dep[e[i].to]=dep[u]+1;q.push(e[i].to);
    			}
    	}
    	return dep[t];
    }
    inline int dfs(int u,int f){
    	if(u==t) return f;
    	int ret=0;
    	for(int i=g[u],d;i&&f;i=e[i].nxt)
    		if(e[i].f>0&&dep[e[i].to]>dep[u]){
    			d=dfs(e[i].to,min(f,e[i].f));
    			f-=d;ret+=d;e[i].f-=d;e[i^1].f+=d;
    		}
    	if(!ret) dep[u]=-1;
    	return ret;
    }
    inline int dinic(){
    	int ret=0;
    	while(bfs(s)) ret+=dfs(s,INF);
    	return ret;
    }
    inline void Aireen(){
    	scanf("%d",&m);
    	while(m--){
    		scanf("%d",&n);
    		k=n*(n-1)/2;
    		s=k+n+11;t=s+1;
    		scanf("%s",ch+1);
    		for(int i=1;i<=n;++i)
    			c[i]=ch[i]-'0';
    		for(int i=0;i<=9;++i)
    			scanf("%d%d",&a[i],&b[i]);
    		sum=0;
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=n;++j)
    				scanf("%d",&w[i][j]);
    		cnt=0;
    		for(int i=1;i<n;++i)
    			for(int j=i+1;j<=n;++j)
    				p[i][j]=++cnt;
    		cnt=1;
    		memset(g,0,sizeof(g));
    		for(int i=1;i<n;++i)
    			for(int j=i+1;j<=n;++j){
    				sum+=w[i][j]+w[j][i];
    				adde(s,p[i][j],w[i][j]+w[j][i]);
    				adde(p[i][j],k+i,INF);adde(p[i][j],k+j,INF);
    			}
    		for(int i=1;i<=n;++i){
    			adde(k+i,k+n+c[i]+1,INF);
    			adde(k+i,t,a[c[i]]);
    		}
    		for(int i=0;i<=9;++i)
    			adde(k+n+i+1,t,b[i]-a[i]);
    		printf("%d\n",sum-dinic());
    	}
    }
    int main(){
    	freopen("value.in","r",stdin);
    	freopen("value.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Python3字典中items()和python2.x中iteritems()有什么区别
    python中使用zip函数出现<zip object at 0x02A9E418>
    python中字符串连接的四种方式
    Python如何规定对方输入的数字必须是整数?
    C# 自定义控件VS用户控件
    c#使用Split分割换行符
    C# 读取app.config配置文件 节点键值,提示 "配置系统未能初始化" 错误的解决方案
    安装MySql for Visual Studio的坑
    MySql Access denied for user 'root'@'localhost' (using password:YES) 解决方案
    VS2010 VS2012 VS2013 VS2015启动调试时老是提示正在下载公共符号
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15612559.html
Copyright © 2011-2022 走看看