E.Grid
省赛时没写出这个题,确实是线段树水平太菜了,现在又想到了这个题,我靠水题。
思路:这个题说白了就是求最大1 到1e9这个区间有多少个点被覆盖,普通线段树空间肯定不行,不过可以用动态开点解决,每次更新最多新花几十个节点的空间,1e5次更新,最多只需几百万的空间足够,解决了这个问题就是水题了。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6; int sum[maxn],ls[maxn],rs[maxn]; int sum2[maxn],ls2[maxn],rs2[maxn],cnt,cnt2; void up(int& o,int l,int r,int ql,int qr) { if(!o)o=++cnt; if(sum[o]==r-l+1)return; if(l>=ql&&r<=qr) { sum[o]=r-l+1; return; } int m=(l+r)/2; if(ql<=m)up(ls[o],l,m,ql,qr); if(qr>m)up(rs[o],m+1,r,ql,qr); sum[o]=sum[ls[o]]+sum[rs[o]]; } void up2(int& o,int l,int r,int ql,int qr) { if(!o)o=++cnt2; if(sum2[o]==r-l+1)return; if(l>=ql&&r<=qr) { sum2[o]=r-l+1; return; } int m=(l+r)/2; if(ql<=m)up2(ls2[o],l,m,ql,qr); if(qr>m)up2(rs2[o],m+1,r,ql,qr); sum2[o]=sum2[ls2[o]]+sum2[rs2[o]]; } int main() { int n,m,q,op,a,b,rt,rt2; while(~scanf("%d%d%d",&n,&m,&q)) { cnt=cnt2=rt=rt2=0; while(q--) { scanf("%d%d%d",&op,&a,&b); if(op==1)up(rt,1,n,a,b); else up2(rt2,1,m,a,b); ll ans=1ll*sum[1]*m+1ll*(n-sum[1])*sum2[1]; ans=1ll*n*m-ans+1; if(sum[1]==0)ans=1ll*(m-sum2[1])*n+sum2[1]; if(sum2[1]==0)ans=1ll*(n-sum[1])*m+sum[1]; printf("%lld\n",ans); } for(int i=1;i<=cnt;i++) sum[i]=ls[i]=rs[i]=0; for(int i=1;i<=cnt2;i++) sum2[i]=ls2[i]=rs2[i]=0; } }