2019.8.25 小结

T1 营业额统计

题意

找前面和这个数相差最小的数,累计差值。

一道大水题!!本来想打打暴力骗骗分的没想到就过了?(雾)

代码

#include<bits/stdc++.h>
using namespace std;
inline int read(){
   int x=0,f=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
       if(ch=='-')
           f=-1;
       ch=getchar();
   }
   while(ch>='0'&&ch<='9'){
       x=(x<<1)+(x<<3)+(ch^48);
       ch=getchar();
   }
   return x*f;
}
int n,a[33000],tmp;
long long ans;
int main(){
   n=read();
   a[1]=read();
   ans+=a[1];
   for(int i=2;i<=n;++i){
   	a[i]=read();
   	tmp=1<<30;
   	for(int j=1;j<i;++j){
   		tmp=min(tmp,abs(a[j]-a[i]));
   	}
   	ans+=tmp;
   }
   printf("%lld",ans);
   return 0;
}

你谷上排序o2才能过

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
struct node{
	int data;
	int num;
}a[33000];
int n,tmp;
long long ans;
bool cmp(node a,node b){
	return a.data<b.data;
}
inline int find(int x){
	int tmp1=1<<30,tmp2=1<<30;
	if(a[x].num==1) return a[x].data;
	for(int i=x-1;i>=1;--i){
		if(a[i].num<a[x].num){
			tmp1=a[x].data>a[i].data ? a[x].data-a[i].data : a[i].data-a[x].data;
			break;
		}
	}
	for(int i=x+1;i<=n;++i){
		if(a[i].num<a[x].num){
			tmp2=a[x].data>a[i].data ? a[x].data-a[i].data : a[i].data-a[x].data;
			break;
		}
	}
	return tmp1>tmp2 ? tmp2 : tmp1;
}
int main(){
	n=read();
	for(int i=1;i<=n;++i){
		a[i].data=read();
		a[i].num=i;
	} 
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;++i){
		ans+=find(i);
	}
	printf("%lld",ans);
	return 0;
}

map大法好

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
multiset<int> a;
multiset<int>::iterator it;
int n,i,b,c,x;
int main(){
	cin>>n;
	for(i=1;i<=n;i++){
		if(scanf("%d",&x)==EOF) x=0;
		a.insert(x);
		if(i==1) c+=x;
		else{
			b=1<<30;
			it=a.find(x);
			if(it!=a.begin()) it--,b=x-(*it),it++;
			it++; if(it!=a.end()) b=min(b,(*it)-x);
			c+=b;
		}
	}
	cout<<c<<endl;
	return 0;
}

T2 dis

问树上两点的最短距离

lca裸题,不多说

代码

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int ver[2*N],Next[2*N],edge[2*N],head[N];
int fa[N],d[N],v[N],lca[N],ans[2*N];
vector<int> query[N],query_id[N];
int n,m,tot,t;
void add(int x,int y,int z){
	ver[++tot]=y;edge[tot]=z;Next[tot]=head[x];head[x]=tot;
}
void add_query(int x,int y,int id){
	query[x].push_back(y),query_id[x].push_back(id);
	query[y].push_back(x),query_id[y].push_back(id);
}
int get(int x){
	if(x==fa[x]) return x;
	else return fa[x]=get(fa[x]);
}
void tarjan(int x){
	v[x]=1;
	for(int i=head[x];i;i=Next[i]){
		int y=ver[i];
		if(v[y]) continue;
		d[y]=d[x]+edge[i];
		tarjan(y);
		fa[y]=x;
	}
	for(int i=0;i<query[x].size();++i){
		int y=query[x][i],id=query_id[x][i];
		if(v[y]==2){
			int lca=get(y);
			ans[id]=min(ans[id],d[x]+d[y]-2*d[lca]);
		}
	}
	v[x]=2;
}
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i) fa[i]=i;
	for(int i=1;i<n;++i){
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		add(x,y,z);add(y,x,z);
	}
	for(int i=1;i<=m;++i){
		int x,y;
		scanf("%d %d",&x,&y);
		if(x==y) ans[i]=0;
		else{
			add_query(x,y,i);
			ans[i]=1<<30;
		}
	}
	tarjan(1);
	for(int i=1;i<=m;++i) printf("%d
",ans[i]);
	return 0;
}

T3 棋盘覆盖

题意

给出一张n* n(n< =100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1* 2的多米诺骨牌进行掩盖。

可转换为二分图最大匹配。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int cx[4]={1,0,0,-1};
int cy[4]={0,1,-1,0};
int n,m,x,y,a[110][110];
bool used[maxn];
int match[maxn];
int tot;
int ver[maxn*2],Next[maxn*2],head[maxn];
void add(int x,int y){
    ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
int getnum(int x,int y){
    return (x-1)*n+y;
}
bool dfs(int x){
    for(int i=head[x];i;i=Next[i]){
        int y=ver[i];
        if(!used[y]){
            used[y]=1;
            if(!match[y]||dfs(match[y])){
                match[y]=x;
                return true;
            }
        }
    }
    return false;
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i){
        scanf("%d %d",&x,&y);
        a[x][y]=1;
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(!a[i][j]){
                for(int p=0;p<4;++p){
                    int nowx=i+cx[p];
                    int nowy=j+cy[p];
                    if(nowx>=1&&nowx<=n&&nowy>=1&&nowy<=n&&!a[nowx][nowy]&&(nowx+nowy)%2){
                        add(getnum(i,j),getnum(nowx,nowy));
                    }
                }
            }
          
        }
    }
    int ans=0;
    for(int i=1;i<=getnum(n,n);++i){
        memset(used,0,sizeof(used));
        if(dfs(i)) ++ans;
    }
    printf("%d",ans);
    return 0;
}

T4 数星星

题意

一道水题,由于x坐标递增y坐标也递增于是前缀和统计即可,用树状数组实现。

#include<bits/stdc++.h>
using namespace std;
const int maxn=15010;
const int maxx=32010;
inline long long read(){
    long long x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
long long n,c[maxx],ans[maxn];
long long lowbit(long long x){
	return x&(-x);
}
void add(long long x){
	for(x;x<=maxx;x+=lowbit(x)) c[x]+=1;
}
long long ask(long long x){
	long long tmp=0;
	for(;x;x-=lowbit(x)) tmp+=c[x];
	return tmp;
}
int main(){
	n=read();
	for(long long i=1;i<=n;++i){
		long long x,y;
		x=read();y=read();
		long long s=ask(x+1);
		add(x+1);
		ans[s]++;
	}
	for(long long i=0;i<n;++i){
		printf("%lld
",ans[i]);
	}
	
	return 0;
}
/*
5 
1 1
5 1
7 1
3 3
5 5
*/
原文地址:https://www.cnblogs.com/donkey2603089141/p/11415038.html