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

    异色弧

    image

    solution

    70分

    \(Let's\;orz\) BearChild!

    朗格拉姆计数

    image

    solution

    60分

    将环复制两遍,预处理出前\(i\)个数中比\(j\)大的数的个数 ,枚举\(a,b\),答案加上\(c\)的个数.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 5001
    #define M 10001
    using namespace std;
    typedef long long ll;
    //s[i][j]表示前i个数中比j大的数的个数 
    ll ans;
    int s[M][N],a[M],n;
    inline int read(){
    	int ret=0;char c=getchar();
    	while(!isdigit(c))
    		c=getchar();
    	while(isdigit(c)){
    		ret=(ret<<1)+(ret<<3)+c-'0';
    		c=getchar();
    	}
    	return ret;
    }
    inline void Aireen(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%d",&a[i]);
    	for(int i=1;i<=n;++i)
    		a[i+n]=a[i];
    	for(int j=1;j<=n;++j)
    		for(int i=1;i<=(n<<1);++i){
    			s[i][j]=s[i-1][j];
    			if(a[i]>j) ++s[i][j];
    		}
    	for(int i=1;i<=n;++i)
    		for(int j=i;j<i+n;++j)
    			if(a[j]>a[i]){
    				ans+=(ll)(s[i+n-1][a[j]]-s[j][a[j]]);
    			}
    	printf("%lld\n",ans);
    }
    int main(){
    	freopen("counter.in","r",stdin);
    	freopen("counter.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    100分

    三元组的形式为\(123,231,312\).
    \(231=XX1-321\).
    \(312=3XX-321\).
    树状数组或线段树维护即可.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 200005
    using namespace std;
    typedef long long ll;
    ll ans;
    int a[N],s[N],g[N],fr[N],be[N],n;
    inline int read(){
    	int ret=0;char c=getchar();
    	while(!isdigit(c))
    		c=getchar();
    	while(isdigit(c)){
    		ret=(ret<<1)+(ret<<3)+c-'0';
    		c=getchar();
    	}
    	return ret;
    }
    inline int lowbit(int x){
    	return x&(-x);
    }
    inline void add(int k){
    	for(int i=k;i<=n;i+=lowbit(i))
    		++s[i];
    }
    inline int ask(int k){
    	int ret=0;
    	for(int i=k;i;i-=lowbit(i))
    		ret+=s[i];
    	return ret;
    }
    inline ll c(int k){
    	return 1ll*k*(k-1)>>1ll;
    } 
    inline void Aireen(){
    	n=read();
    	for(int i=1;i<=n;++i){
    		a[i]=read();g[a[i]]=i;
    	}
    	for(int i=1;i<=n;++i){
    		fr[i]=ask(g[i]-1);
    		be[i]=ask(n)-ask(g[i]);
    		add(g[i]);
    	}
    	memset(s,0,sizeof(s));
    	for(int i=n,f,b;i;--i){
    		f=ask(g[i]-1);
    		b=ask(n)-ask(g[i]);
    		add(g[i]);
    		ans+=1ll*fr[i]*b;//123
    		ans+=c(be[i])-1ll*f*be[i];//312
    		ans+=c(f)-1ll*f*be[i];//231 
    	}
    	printf("%lld\n",ans);
    }
    int main(){
    	freopen("counter.in","r",stdin);
    	freopen("counter.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    修路

    image

    solution

    斯坦纳树

    \(f[i][j]\)表示以\(i\)为根的树中,连通的节点的状态为\(j\)的最小/大权值.
    \(f[i][j]=min\{f[i][l]+f[i][l^j]\}\),\(l\)\(j\)的子集.
    \(f[i][j]=min\{f[k][j]+g[k][i]\}\),这可以用\(spfa\)\(dijkstra\)求解.

    100分

    用斯坦纳树求出\(f[\;][\;]\)数组.
    如果在状态\(j\)中,\(i\)\(n-i+1\)\(j\)中或都不在\(j\)中,\(g[j]=min\{f[i][j]\}\)(保证\(i\)\(n-i+1\)连通).
    \(g[i]=min\{g[j]+g[i^j]\}j\)\(i\)的子集\()\).

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define K 8
    #define N 10005
    #define M 20005
    #define INF 10000000
    #define min(a,b) a<b?a:b
    using namespace std;
    int nxt[M],to[M],w[M];
    int f[N][1<<K],ff[1<<K],g[N],q[INF],h,t,n,m,k,d,cnt;
    bool inq[N];
    inline int read(){
    	int ret=0;char c=getchar();
    	while(!isdigit(c))
    		c=getchar();
    	while(isdigit(c)){
    		ret=(ret<<1)+(ret<<3)+c-'0';
    		c=getchar();
    	}
    	return ret;
    }
    inline void addedge(int x,int y,int z){
    	nxt[++cnt]=g[x];g[x]=cnt;to[cnt]=y;w[cnt]=z;
    }
    inline void spfa(int k){
    	int u;
    	while(h<=t){
    		u=q[h++];inq[u]=false;
    		for(int i=g[u];i;i=nxt[i])
    			if(f[u][k]+w[i]<f[to[i]][k]){
    				f[to[i]][k]=f[u][k]+w[i];
    				if(!inq[to[i]]){
    					inq[to[i]]=true;q[++t]=to[i];
    				}
    			}
    	} 
    }
    inline bool chk(int s){
    	for(int i=1;i<=d;++i)
    		if((bool)(s&(1<<i-1))^(bool)(s&(1<<k-i)))
    			return false;
    	return true;
    }
    inline void Aireen(){
    	n=read();m=read();d=read();
    	for(int i=1,x,y,w;i<=m;++i){
    		x=read();y=read();w=read();
    		addedge(x,y,w);addedge(y,x,w);
    	}
    	k=d<<1;
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<(1<<k);++j)
    			f[i][j]=INF;
    	for(int i=1;i<=d;++i)
    		f[i][1<<i-1]=f[n-i+1][1<<k-i]=0;
    	for(int j=0;j<(1<<k);++j){
    		h=1;t=0;
    		for(int i=1;i<=n;++i){
    			for(int l=j;l;l=(l-1)&j)
    				f[i][j]=min(f[i][j],f[i][l]+f[i][j^l]);
    			if(f[i][j]<INF){
    				inq[i]=true;q[++t]=i; 
    			}
    		}
    		spfa(j);
    	}
    	for(int j=0;j<(1<<k);++j){
    		ff[j]=INF;
    		if(chk(j)){
    			for(int i=1;i<=n;++i)
    				ff[j]=min(ff[j],f[i][j]); 
    		}
    	}
    	for(int j=0;j<(1<<k);++j)
    		for(int l=j;l;l=(l-1)&j)
    			ff[j]=min(ff[j],ff[j^l]+ff[l]);
    	if(ff[(1<<k)-1]==INF) puts("-1");
    	else printf("%d\n",ff[(1<<k)-1]);
    }
    int main(){
    	freopen("road.in","r",stdin);
    	freopen("road.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    iOS学习-UILabel
    react js
    代理模式
    利用gitbush从git上下载代码到本地
    VS2017企业版密钥
    office2016产品密钥及激活工具
    .netframe初识
    树的遍历——c#实现
    数据结构——总结
    单例模式
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15609507.html
Copyright © 2011-2022 走看看