zoukankan      html  css  js  c++  java
  • 9.15上课日记

    part1

    逆序对
    详见代码
    顺带归并排序一起复习

    #include<bits/stdc++.h>
    using namespace std;
    int a[100001],b[100001];
    long long ans=0;
    void lala(int l,int m,int r){
    	int i=l,k=l,j=m+1;//i左区间,j右区间 
    	while(i<=m&&j<=r){
    		if(a[i]>a[j]){//左大于右(逆序了)下来一个右区间
    			b[k]=a[j];k++,j++;
    			ans+=m-i+1;
    		}
    		else b[k++]=a[i++];//下来一个左区间(没有逆序) 
    	}
    	while(i<=m)b[k++]=a[i++];//对于剩余部分直接加入 
    	while(j<=r)b[k++]=a[j++];
    	for(int i=l;i<=r;i++){//重排
    		a[i]=b[i];
    	}
    }
    void guibing(int l,int r){
    	if(l<r){
    		int m=l+r>>1;
    		guibing(l,m);
    		guibing(m+1,r);
    		lala(l,m,r);
    	}
    }
    int main(){
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	guibing(1,n);
    	cout<<ans;
    	return 0;
    }
    

    然后,我按照题解写了个树状数组

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int a[1000101],b[1000101],c[1000101];
    int n;
    bool cmp(int x,int y){
    	return b[x]>b[y];
    }
    void add(int x,int cc){
    	for(;x<n;x+=(x&(-x)))
    		c[x]+=cc;
    }
    int query(int x){
    	int ans=0;
    	for(;x>0;x-=(x&(-x)))
    		ans+=c[x];
    	return ans;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&b[i]);
    		a[i]=i;
    	}
    	sort(a+1,a+n+1,cmp);
    	int anss=0;
    	for(int i=1;i<=n;i++){
    		add(a[i],1);
    		anss+=query(a[i]-1);
    	}
    	cout<<anss;
    } 
    

    挂的妈都不认识....
    输出和正确答案一毛一样
    算了,再说

    part 2

    搜索优化
    预告
    n皇后与魔板
    对于n皇后,这次选择的是带状压的n<=14的版本
    顺手练练状压了
    先放个基础n皇后

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int h[100][100]={0},l[100][100]={0},d1[100]={0},d2[100]={0};
    int a[100]={0},b[100]={0};
    int ans=0,n;
    void  dfs(int x){
    	if(x==n+1){
    //		if(ans<=2){
    //			for(int i=1;i<=n;i++)cout<<b[i]<<' ';
    //		cout<<endl;
    //		}
    		ans++;return ;
    	}
    	for(int i=1;i<=n;i++){
    		if(h[x][i]==0&&l[x][i]==0&&d1[x+i]==0&&d2[x-i+n]==0){
    			b[x]=i;for(int j=1;j<=n;j++)l[j][i]=1;
    			d1[x+i]=1;d2[x-i+n]=1;//cout<<i<<endl;
    			dfs(x+1);
    			b[x]=0;for(int j=1;j<=n;j++)if(h[j][i]==0)l[j][i]=0;
    			l[x][i]=0;d1[x+i]=0;d2[x-i+n]=0;
    		}
    	}
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++){
    			char c;
    			cin>>c;
    			if(c=='.')h[i][j]=1;
    		}
    	dfs(1);
    	cout<<ans;
    	return 0;
    }
    

    这是个60分代码
    那么这个n=14看来是真的坑了
    我仔细看了看位运算,觉得当年的lower老是写挂是有道理的
    可惜今天恐怕调不出来了,明天继续;
    先转载一篇题解
    原链接

    #include<bits/stdc++.h>
    using namespace std;//用位运算优化
    int n,mans,p;
    int mark[100],bin[1<<20];
    void dfs(int x/*行*/,int a,int b,int c){//列,左上角,右上角标记 
        if(x>n){
            ans++;
            if(ans>=1&&ans<=3){
                for(int i=1;i<=n;i++)printf("%d ",mark[i]+1);//输出标记了的列 
                puts("");
            }
            return;
        }
        int t=(a|b|c)^p;//p记录棋盘下标范围,t判断是否在棋盘内
        while(t) {
            int i=t&(-t);//二进制找到最后一个的全值 
            mark[x]=bin[i];//选择当前棋子 
            dfs(x+1,a|i,(b|i)>>1,((c|i)<<1)&p);//对当前棋子做标记,继续查找 
    //a|i记录当前列不能走,b|i表示左上角,(c|i)<<1)&p查找右上角与当前列的重合 
            t-=i;
        }
    }
    int main(){
        scanf("%d",&n);
        p=(1<<n)-1;//用二进制表示下标范围;
        bin[0]=1;
        for(int i=1; i<=n; i++)bin[1<<i]=i;//二进制标记归位 
        dfs(1,0,0,0);
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    Nginx 使用 GeoIP 模块区分用户地区
    使用nginx转发tcp请求(解决访问内网的腾讯云redis)
    open file cache提升nginx性能
    使用 nginx-http-concat
    使用goaccess对Nginx日志简单分析
    Zookeeper系列一:Zookeeper基础命令操作
    k8s nginx应用-获取客户端访问真实IP
    mysql 备份数据库中的一张表
    ssh命令带密码
    Linux下grep显示前后几行信息
  • 原文地址:https://www.cnblogs.com/lisuier/p/9651788.html
Copyright © 2011-2022 走看看