查询行区间得到列的最大最小值
查询列区间得到行的最大最小值
。。。。
然后就不TLE了
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=3e5+100;
typedef __int64 LL;
int lg[N],mi[22];
void init(){
lg[0]=-1;
int c=1;
for(int i=1;i<N;i++){
if(i==c){
lg[i]=lg[i-1]+1;
c*=2;
}
else {
lg[i]=lg[i-1];
}
}
mi[0]=1;
for(int i=1;i<=20;i++){
mi[i]=mi[i-1]*2;
}
}
int n;
void up(int dp[N][22],int aa[N],int op){
for(int i=1;i<=n;i++)dp[i][0]=aa[i];
for(int i=1;i<=lg[n];i++){
for(int j=1;j+mi[i]-1<=n;j++){
if(op==0){
dp[j][i]=min(dp[j][i-1],dp[j+mi[i-1]][i-1]);
}
else {
dp[j][i]=max(dp[j][i-1],dp[j+mi[i-1]][i-1]);
}
}
}
}
int query(int dp[N][22],int l,int r,int op){
int k=lg[r-l+1];
if(op==0){
return min(dp[l][k],dp[r-mi[k]+1][k]);
}
else {
return max(dp[l][k],dp[r-mi[k]+1][k]);
}
}
int xx[4][N][22];
int rr[N],dp[N];
int aa[N],bb[N];
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
init();
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
int a,b;scanf("%d%d",&a,&b);
aa[a]=b;
bb[b]=a;
}
up(xx[0],aa,0);
up(xx[1],aa,1);
up(xx[2],bb,0);
up(xx[3],bb,1);
for(int i=n;i>=1;i--){
int r=i+1;
dp[i]=1;
rr[i]=i;
while(r<=n){
int ma=query(xx[0],i,r,0),mb=query(xx[1],i,r,1);
int xa=query(xx[2],ma,mb,0),xb=query(xx[3],ma,mb,1);
if(xa==i&&xb==r){
rr[i]=rr[r];
dp[i]+=dp[r];
r=rr[r]+1;
}
else if(xa<i){
break;
}
else {
r=xb;
}
}
}
LL ans=0;
for(int i=1;i<=n;i++){
ans+=dp[i];
}
printf("%I64d\n",ans);
}
return 0;
}