题解 P1496 【火烧赤壁】
蒟蒻的第一篇题解,其实这道题是标准的离散化,模拟可以过,但是就没有训练效果了。我们首先先看数据,n<=20000,数据不多,但是范围大(-10^9<=Ai,Bi<=10^9),这时,就可以用离散化了,我们先定义两个数组,记录坐标,再全部赋给一个新的数组,进行排序,就可以判断是否可用*(flag判断),再通过一个find函数,找到原位置,就可以算了。但是本题卡时间,优化一下就行(快读,氧气优化之类的)
关于判断是否可用,举个栗子
有两对线段(x1,y1)(x2,y2) 如果x1>y2或x2>y1,那么(y2,x1)段或(y1,x2)段无用
1 #pragma GCC optimize(2)//手动o2 2 #include<iostream> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cmath> 6 #include<cstring> 7 using namespace std; 8 long n,m=1,ans=0;//m记录坐标数 9 long c[40100]={0}; 10 //因为c要把起点与终点存下来,所以开40100 11 int a[20100],b[20100];//a存起点,b存终点 12 bool flag[40100];//判断是否有效 13 inline void read(long &x)//快读 14 { 15 x=0; 16 int f=1; 17 char ch=getchar(); 18 while(ch<'0'||ch>'9') 19 { 20 if(ch=='-') 21 f=-1; 22 ch=getchar(); 23 } 24 while(ch>='0'&&ch<='9') 25 { 26 x=x*10+ch-'0'; 27 ch=getchar(); 28 } 29 x*=f; 30 } 31 inline long find(long key)//找原来位置 32 { 33 for(int i=1;i<=m;++i) 34 { 35 if(c[i]==key) 36 return i; 37 } 38 } 39 int main() 40 { 41 read(n); 42 for(long i=1;i<=n;++i) 43 { 44 read(a[i]); 45 read(b[i]); 46 c[m]=a[i]; 47 m++; 48 c[m]=b[i]; 49 m++; 50 }//把a,b存入c数组里去 51 sort(c+1,c+m+1);//排序坐标 52 for(long i=1;i<=n;++i) 53 { 54 a[i]=find(a[i]); 55 b[i]=find(b[i])-1;//找原位置 56 for(int j=a[i];j<=b[i];++j) 57 flag[j]=true;//为有效 58 } 59 for(long i=1;i<=m;++i) 60 { 61 if(flag[i]) 62 ans+=c[i+1]-c[i];//有效,加入ans 63 } 64 printf("%ld",ans); 65 }
蒟蒻瑟瑟发抖,%%各位大佬