杨思越
(灵珠敖丙)
1
1. 牛牛的围栏
题目ID:21636必做题100分
时间限制: 1000ms
空间限制: 262144kB
题目描述
农夫约翰有一片巨大的二维网格状牧场(想象一个超大的棋盘)。目前有N头奶牛(1≤N≤2500)分布在不同的网格单元中。约翰想要建造一个围栏,围住一个矩形区域内的奶牛子集。这个矩形必须与x轴和y轴平行,最小可以只包含一个单元格。请帮他计算可以围住的不同奶牛子集数量(包括空子集)。
输入格式
第一行:整数N(奶牛数量)
接下来N行:每行两个整数,表示奶牛的(x,y)坐标
所有x坐标互不相同,所有y坐标也互不相同
坐标值范围:0到10^9
输出格式
可围住的奶牛子集总数(保证可以用64位有符号整数存储)(long long in C/C++)
样例
Input 1
4 0 2 1 0 2 3 3 5
Output 1
13
样例解释
总共有2^4=16个子集。无法围住的子集有:
仅包含奶牛1、2、4
仅包含奶牛2、4
仅包含奶牛1、4
因此答案为16-3=13
数据范围
测试点2-3:N≤20
测试点4-6:N≤100
测试点7-12:N≤500
测试点13-20:无额外限制
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int x,int y){
return x<y;
}
int n;
struct box{
int x,y;
}cow[505];
int x[505],y[505];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
cow[i].x=x[i];
cow[i].y=y[i];
}
sort(x+1,x+1+n,cmp);
sort(y+1,y+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cow[i].x==x[j]){
cow[i].x=j;
break;
}
}
for(int j=1;j<=n;j++){
if(cow[i].y==y[j]){
cow[i].y=j;
break;
}
}
}
/*for(int i=1;i<=n;i++){
cout<<cow[i].x<<" "<<cow[i].y<<endl;
}*/
ll ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
//选定cow[i],cow[j]为上下区间
ans=ans+min(cow[i].x,cow[j].x)*abs(cow[i].y-cow[j].y);
ans=ans+(n-1-max(cow[i].x,cow[j].x))*abs(cow[i].y-cow[j].y);
}
}
cout<<ans;
return 0;
}
/*
\__/
\ / \ /
—|o_o | —
/\ _ /\
/ \
00000000-0010-0824-0000-000000000000
*/
杨思越
(灵珠敖丙)
7
现在代码是这样:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int x,int y){
return x<y;
}
int n;
struct box{
int x,y;
}cow[505];
int x[505],y[505];
int qq[505][505];
int get_(int x1,int y_,int x2,int y2){
return qq[x2+1][y2+1]-qq[x2+1][y_]-qq[x1][y2+1]+qq[x1][y_];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
cow[i].x=x[i];
cow[i].y=y[i];
}
sort(x+1,x+1+n,cmp);
sort(y+1,y+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cow[i].x==x[j]){
cow[i].x=j;
break;
}
}
for(int j=1;j<=n;j++){
if(cow[i].y==y[j]){
cow[i].y=j;
break;
}
}
}
/*for(int i=1;i<=n;i++){
cout<<cow[i].x<<" "<<cow[i].y<<endl;
}*/
for(int i=1;i<=n;i++){
qq[cow[i].x][cow[i].y]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
qq[i][j]+=qq[i-1][j]+qq[i][j-1]-qq[i-1][j-1];
}
}
ll ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
//选定cow[i],cow[j]为上下区间
int x1=min(cow[i].x,cow[j].x);
int x2=max(cow[i].y,cow[j].y);
ans+=get_(0,i,x1,j)*get_(x2,i,n-1,j);
}
}
cout<<ans;
return 0;
}
/*
\__/
\ / \ /
—|o_o | —
/\ _ /\
/ \
00000000-0010-0824-0000-000000000000
*/
样例不过
360病毒
(只会打暴力的人)
8
第一,ans初始值要为n
,因为单独一头奶牛也是一种方案;
第二,get
返回值要加1;
第三,统计答案时,j从i+1开始枚举
杨思越
(灵珠敖丙)
9
样例过,RE5
#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int x,int y){
return x<y;
}
int n;
struct box{
int x,y;
}cow[505];
int x[505],y[505];
int qq[505][505];
int get_(int x1,int y_,int x2,int y2){
return qq[x2+1][y2+1]-qq[x2+1][y_]-qq[x1][y2+1]+qq[x1][y_]+1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
cow[i].x=x[i];
cow[i].y=y[i];
}
sort(x+1,x+1+n,cmp);
sort(y+1,y+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cow[i].x==x[j]){
cow[i].x=j;
break;
}
}
for(int j=1;j<=n;j++){
if(cow[i].y==y[j]){
cow[i].y=j;
break;
}
}
}
/*for(int i=1;i<=n;i++){
cout<<cow[i].x<<" "<<cow[i].y<<endl;
}*/
for(int i=1;i<=n;i++){
qq[cow[i].x][cow[i].y]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
qq[i][j]+=qq[i-1][j]+qq[i][j-1]-qq[i-1][j-1];
}
}
ll ans=n;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
//选定cow[i],cow[j]为上下区间
int x1=min(cow[i].x,cow[j].x);
int x2=max(cow[i].y,cow[j].y);
ans+=get_(0,i,x1,j)*get_(x2,i,n-1,j);
}
}
cout<<ans;
return 0;
}
/*
\__/
\ / \ /
—|o_o | —
/\ _ /\
/ \
00000000-0010-0824-0000-000000000000
*/
杨思越
(灵珠敖丙)
11
WA5
#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool cmp(int x,int y){
return x<y;
}
int n;
struct box{
int x,y;
}cow[2503];
int x[2503],y[2503];
int qq[2503][2503];
int get_(int x1,int y_,int x2,int y2){
return qq[x2+1][y2+1]-qq[x2+1][y_]-qq[x1][y2+1]+qq[x1][y_]+1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
cow[i].x=x[i];
cow[i].y=y[i];
}
sort(x+1,x+1+n,cmp);
sort(y+1,y+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cow[i].x==x[j]){
cow[i].x=j;
break;
}
}
for(int j=1;j<=n;j++){
if(cow[i].y==y[j]){
cow[i].y=j;
break;
}
}
}
/*for(int i=1;i<=n;i++){
cout<<cow[i].x<<" "<<cow[i].y<<endl;
}*/
for(int i=1;i<=n;i++){
qq[cow[i].x][cow[i].y]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
qq[i][j]+=qq[i-1][j]+qq[i][j-1]-qq[i-1][j-1];
}
}
ll ans=n;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
//选定cow[i],cow[j]为上下区间
int x1=min(cow[i].x,cow[j].x);
int x2=max(cow[i].y,cow[j].y);
ans+=get_(0,i,x1,j)*get_(x2,i,n-1,j);
}
}
cout<<ans;
return 0;
}
/*
\__/
\ / \ /
—|o_o | —
/\ _ /\
/ \
00000000-0010-0824-0000-000000000000
*/
求二维前缀和的x1 x2这种别搞混,你的离散化以及输入的时候有的是从1开始,有的是从0开始,你的二维前缀和是从1开始的
杨思越
(灵珠敖丙)
19
全WA
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct box{
int x,y;
}cow[2503];
bool cmp(int x,int y){
return x<y;
}
bool cmp1(box x,box y){
return x.y<y.y;
}
int n;
int x[2503],y[2503];
int qq[2503][2503];
int get_(int x1,int y_,int x2,int y2){
return qq[x2+1][y2+1]-qq[x2+1][y_]-qq[x1][y2+1]+qq[x1][y_];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
cow[i].x=x[i];
cow[i].y=y[i];
}
sort(x+1,x+1+n,cmp);
sort(y+1,y+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cow[i].x==x[j]){
cow[i].x=j;
break;
}
}
for(int j=1;j<=n;j++){
if(cow[i].y==y[j]){
cow[i].y=j;
break;
}
}
}
/*for(int i=1;i<=n;i++){
cout<<cow[i].x<<" "<<cow[i].y<<endl;
}*/
for(int i=1;i<=n;i++){
qq[cow[i].x][cow[i].y]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
qq[i][j]+=qq[i-1][j]+qq[i][j-1]-qq[i-1][j-1];
}
}
sort(cow,cow+n,cmp1);
ll ans=n;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
//选定cow[i],cow[j]为上下区间
int x1=min(cow[i].x,cow[j].x);
int x2=max(cow[i].x,cow[j].x);
ans+=get_(0,i,x1,j)*get_(x2,i,n-1,j);
}
}
cout<<ans+1;
return 0;
}
/*
\__/
\ / \ /
—|o_o | —
/\ _ /\
/ \
00000000-0010-0824-0000-000000000000
*/
你的cow是从1开始的,那应该是 sort(cow+1,cow+n+1,cmp1);`