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\n",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\n",ans[i]);
}
return 0;
}
/*
5
1 1
5 1
7 1
3 3
5 5
*/