人生的第一次div.1 掉分 QAQ
http://codeforces.com/contest/853/problem/A
贪心,排个序,优先安排花费大的,用模拟链表实现的
#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
struct node
{
int t,index;
}a[1000005];
int cmp(node u,node v)
{
return u.t>v.t;
}
int pre[1000005],ne[1000005];
int ans[1000000];
int book[1000000];
int main()
{
int n,k,i;
cin>>n>>k;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i].t);
a[i].index=i;
}
for(i=0;i<=1000000;i++)
{
if(i!=0)
pre[i]=i-1;
ne[i]=i+1;
}
sort(a+1,a+1+n,cmp);
long long sum=0;
int now=k+1;
for(i=1;i<=n;i++)
{
if(a[i].index<=now)
{
sum+=1ll*(now-a[i].index)*a[i].t;
ans[a[i].index]=now;
ne[pre[now]]=ne[now];
pre[ne[now]]=pre[now];
now=ne[now];
}
else
{
ans[a[i].index]=a[i].index;
ne[pre[a[i].index]]=ne[a[i].index];
pre[ne[a[i].index]]=pre[a[i].index];
}
}
cout<<sum<<endl;
for(i=1;i<=n;i++)
printf("%d ",ans[i]);
cout<<endl;
}
http://codeforces.com/contest/853/problem/B
题意看了半天,看懂题意,其实就很水了。。
也是排个序,记录一下前缀最小花费,后缀最小花费,最后扫一遍就可以了
#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
int n,m,k;
long long dp[2][1000005];
long long need[2][1000005];
struct node
{
int d,f,t,c;
}a[100005];
int cmp(node u,node v)
{
return u.d<v.d;
}
const ll inf=0x3f3f3f3f3f3f3f3f;
int main()
{
int i;
cin>>n>>m>>k;
for(i=0;i<m;i++)
{
scanf("%d %d %d %d",&a[i].d,&a[i].f,&a[i].t,&a[i].c);
}
sort(a,a+m,cmp);
memset(need,-1,sizeof(need));
memset(dp,inf,sizeof(dp));
ll sum=0,now=0;
for(i=0;i<m;i++)
{
if(a[i].f)
{
if(need[0][a[i].f]==-1)
{
now++;
sum+=a[i].c;
need[0][a[i].f]=a[i].c;
}
else if(a[i].c<need[0][a[i].f])
{
sum+=a[i].c-need[0][a[i].f];
need[0][a[i].f]=a[i].c;
}
if(now==n)
{
dp[0][a[i].d]=min(dp[0][a[i].d],sum);
}
}
}
now=0,sum=0;
for(i=m-1;i>=0;i--)
{
if(a[i].t)
{
if(need[1][a[i].t]==-1)
{
now++;
sum+=a[i].c;
need[1][a[i].t]=a[i].c;
}
else if(a[i].c<need[1][a[i].t])
{
sum+=a[i].c-need[1][a[i].t];
need[1][a[i].t]=a[i].c;
}
if(now==n)
{
dp[1][a[i].d]=min(dp[1][a[i].d],sum);
}
}
}
for(i=1;i<=1000000;i++)
{
dp[0][i]=min(dp[0][i],dp[0][i-1]);
}
for(i=1000000;i>=0;i--)
{
dp[1][i]=min(dp[1][i],dp[1][i+1]);
}
long long ans=inf;
for(i=0;i+k<=1000000;i++)
{
ans=min(ans,dp[0][i]+dp[1][i+k+1]);
}
if(ans==inf)
cout<<-1<<endl;
else
cout<<ans<<endl;
return 0;
}
C - Boredom
http://codeforces.com/contest/853/problem/C
主席树,主席树主要是用来快速统计某个子矩阵里标记点的个数,因为每列只被标记一个,所以主席树可以搞,但当时思路并不是很清晰,手速也太慢,后来想通了其实也还好
这样就可以快速的查询某个子矩阵里标记点的个数,对于每个查询的矩阵,我们只需要求不在这个矩阵里的所有 beautiful rectangles个数即可,也就是两个被标记的点都在查询矩阵的上方,下方,左方,右方,最后在去一下重。
#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int l[30*maxn],r[30*maxn],sz[30*maxn];
int tot=0,t[maxn],p[maxn];
int build(int le,int ri)
{
int root=tot++;
sz[root]=0;
int m=(le+ri)>>1;
if(le!=ri)
{
l[root]=build(le,m);
r[root]-build(m+1,ri);
}
return root;
}
int update(int root,int le,int ri,int x,int k)
{
int now=tot++;
sz[now]=sz[root]+k;
if(le==ri)
return now;
int m=(le+ri)>>1;
if(x<=m)
{
l[now]=update(l[root],le,m,x,k);
r[now]=r[root];
}
else
{
r[now]=update(r[root],m+1,ri,x,k);
l[now]=l[root];
}
return now;
}
int query(int root,int le,int ri,int L,int R)
{
if(L>R)
return 0;
if(L<=le&&R>=ri)
{
return sz[root];
}
if(le==ri)
{
return sz[root];
}
int sum=0;
int m=(le+ri)>>1;
if(m>=L)
{
sum+=query(l[root],le,m,L,R);
}
if(m<R)
{
sum+=query(r[root],m+1,ri,L,R);
}
return sum;
}
inline long long f(int x)
{
return 1ll*x*(x-1)/2;
}
int main()
{
int i,n,q,l,r,u,d;
cin>>n>>q;
t[0]=build(1,n);
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
t[i]=update(t[i-1],1,n,p[i],1);
}
long long ans=0;
// cout<<query(t[0],1,n,1,n)<<endl;
while(q--)
{
ans=f(n);
scanf("%d %d %d %d",&l,&d,&r,&u);
int temp1=query(t[n],1,n,1,n)-query(t[r],1,n,1,n);
int temp2=query(t[n],1,n,u+1,n);
int temp3=temp2-query(t[r],1,n,u+1,n);
int temp4=query(t[l-1],1,n,1,n);
int temp5=query(t[n],1,n,1,d-1);
int temp6=temp5-query(t[r],1,n,1,d-1);
int temp7=temp4-query(t[l-1],1,n,1,u);
int temp8=query(t[l-1],1,n,1,d-1);
// cout<<temp1<<" "<<temp2<<" "<<temp3<<" "<<temp4<<" "<<temp5<<" "<<temp6<<" "<<temp7<<" "<<temp8<<endl;
ans-=f(temp1)+f(temp2)+f(temp4)+f(temp5)-f(temp3)-f(temp7)-f(temp8)-f(temp6);
printf("%lld\n",ans);
}
return 0;
}