1. 程式人生 > >JZOJ 數數

JZOJ 數數

tchar mes style span algorithm iostream return pre namespace

二進制通常通過拆位來做,類歐幾裏得f裸題,直接上代碼;

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=2505;
const int inf=1000000000;
const int M=2500;

int n,s[N][N],ur[N][N],dl[N][N],ul[N][N],dr[N][N],drd[N][N],drr[N][N],ulu[N][N],ull[N][N];
struct data{int x,y;}a[250005]; 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*10+ch-0;ch=getchar();} return x*f; } int get_dl(int x,int y) { if (x<1||x>M||y<1||y>M) return
0; if (dl[x][y]>-1) return dl[x][y]; dl[x][y]=0; int d=min(drd[x][y+1],x),l=min(ull[x+1][y],y); return dl[x][y]=get_dl(d,l)+dr[x][1]-dr[x][y+1]; } int get_ur(int x,int y) { if (x<1||x>M||y<1||y>M) return 0; if (ur[x][y]>-1) return ur[x][y]; ur[x][y]=0;
int u=max(ulu[x][y-1],x),r=max(drr[x-1][y],y); return ur[x][y]=get_ur(u,r)+ul[x][M]-ul[x][y-1]; } int main() { n=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].y=M-a[i].y+1,s[a[i].x][a[i].y]++; for (int i=0;i<=M+1;i++) for (int j=0;j<=M+1;j++) { ull[i][j]=drd[i][j]=inf; ulu[i][j]=drr[i][j]=-1; dl[i][j]=ur[i][j]=-1; } for (int i=M;i>=1;i--) for (int j=1;j<=M;j++) { ull[i][j]=min(ull[i][j-1],ull[i+1][j]); ulu[i][j]=max(ulu[i][j-1],ulu[i+1][j]); if (s[i][j]) ull[i][j]=min(ull[i][j],j),ulu[i][j]=max(ulu[i][j],i); ul[i][j]=ul[i][j-1]+ul[i+1][j]-ul[i+1][j-1]+s[i][j]; } for (int i=1;i<=M;i++) for (int j=M;j>=1;j--) { drr[i][j]=max(drr[i][j+1],drr[i-1][j]); drd[i][j]=min(drd[i][j+1],drd[i-1][j]); if (s[i][j]) drr[i][j]=max(drr[i][j],j),drd[i][j]=min(drd[i][j],i); dr[i][j]=dr[i][j+1]+dr[i-1][j]-dr[i-1][j+1]+s[i][j]; } for (int i=1;i<=n;i++) { int x=a[i].x,y=a[i].y; int ans=get_dl(x,y)+get_ur(x,y)+n-3; printf("%d\n",ans); } return 0; }

JZOJ 數數