10 22
额 今天题目还行不过我状态不好什么都没写出来... 今天得分80.T1 30 T2 10分 T3 40分
但是我不能否定的是 题目质量还是很不错的 暴露的一些问题:
1 我又又又读错题目了 2 我又又又刚题了 一个显然的模型我一直写qwq 3 剩下的还行.
此题 毒瘤 我尝试了各种 行之无效的方法 思考2h 不断尝试 新的方法 各种种建边 删边 建反图 无向最短路树 ...都被我思考了一番发现还是不能解决复杂度高的问题。或者有环又回到自己的问题。
关于正解 我也并不认为其复杂度是行之有效的 (好吧我最终接受了其时间复杂度 对于每个点 bfs一次所以复杂度 nm
服了自闭qwq.什么动态spfa 什么 LCA合并法...其实是次短路罢了.我想到一个简洁的方法 不知道对不对. 果然还是错误的还是可能发生不合法的情况需要记录一下某条边是从哪里过来的。
不妨再深入思考一下。
此题注意读题 求一个矩形和其他矩形的交的和 注意这里是和 也就是说一个矩形和其他矩形进行交 然后求和 读错题变成了 一个矩形和所有矩形的交
瞬间变的不可做了 交的地方 需要取交 很复杂 我想到一个暴力 指针向右扫然后 线段树区间取交 标记永久化来实现 线段树太多不可能下放懒标记的。那么我们可以直接树套树了。
这里不说错误的题了 考虑正确的读题正确的思考 我真服了凭空给自己出了一道非常难写的题目 我认为 多个矩形取交一定又更优秀的做法 我想是树套树 还好我没写树套树 线段树套线段树我都不知道怎么写来着的了。
况且空间也开不下 。矩形的面积的交的和 考虑怎么求 发现还是类似于扫描的套路 扫一下即可。
没想好 咕了。由于某人当时A掉了此题过后还是不太会无奈我不咕这道题好了 整理一下统计答案的方式 和 方法。
1 首先是面积交的和 而并非交 2 暴力很显然吧 对于30 分二维前缀和即可 数组开vector 对于60分 考虑树套树 难写 对时间和空间 要求较高 还要标记永久化什么的 。
3 正解 考虑将问题离线下来 ,将一个矩形分成两部分一个大矩形和一个小矩形 做差得到答案 (强制降维 剩下的只要按照横坐标排序就可以实现降维的操作了因为左边有容斥 右边有排序 都是y轴上的问题了。
一颗线段树维护y轴 考虑如何维护答案?由于查询时 和 被查询的矩形都 得被分且有关系 所以需要构造一种统计答案的方式即可。
方式可能有很多这里我 想了一种很独特的方式... 对于存在的矩形来看统计答案的时候 我们考虑一条线出现之后带来的贡献 后面的 面积 减掉 然后维护纵坐标的len长度即可。
和这条线相对的呢 线减掉加上面积即可。 至于 查询矩形可以直接做了 累加 len和面积即可。
奉上写了一下午的代码 原因是 y轴可能为0 但我线段树的值域是 1~L 所以挂了 源神一眼帮我看出来了 真强qwq.
//#include<bits/stdc++.h> #include<iomanip> #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<deque> #include<cmath> #include<ctime> #include<cstdlib> #include<stack> #include<algorithm> #include<vector> #include<cctype> #include<utility> #include<set> #include<bitset> #include<map> #define INF 1000000000 #define ll long long #define min(x,y) ((x)>(y)?(y):(x)) #define max(x,y) ((x)>(y)?(x):(y)) #define RI register ll #define db double #define pii pair<ll,ll> #define mk make_pair #define l(p) s[p].l #define r(p) s[p].r #define sum(p) s[p].sum #define len(p) s[p].len #define tag(p) s[p].tag #define laz(p) s[p].laz #define zz p<<1 #define yy p<<1|1 using namespace std; char *fs,*ft,buf[1<<15]; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline ll read() { ll x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } const ll MAXN=500010; ll n,m,cnt; ll W,L; ll ans[MAXN]; struct wy { ll op; ll x,s1,s2; ll len,s; ll friend operator <(wy a,wy b) { return a.x==b.x?a.op<b.op:a.x<b.x; } }t[MAXN<<2]; struct jl { ll l,r; ll sum,len;//sum维护面积 len 维护长度 ll tag,laz;//tag维护面积lazy tag laz维护长度lazy tag }s[MAXN<<2]; inline void build(ll p,ll l,ll r) { l(p)=l;r(p)=r; if(l==r)return; ll mid=(l+r)>>1; build(zz,l,mid); build(yy,mid+1,r); } inline void pushup(ll p) { sum(p)=sum(zz)+sum(yy); len(p)=len(zz)+len(yy); return; } inline void pushdown(ll p) { ll mid=(l(p)+r(p))>>1; if(tag(p)) { sum(zz)+=(mid-l(p)+1)*tag(p); tag(zz)+=tag(p); sum(yy)+=(r(p)-mid)*tag(p); tag(yy)+=tag(p); tag(p)=0; } if(laz(p)) { len(zz)+=(mid-l(p)+1)*laz(p); laz(zz)+=laz(p); len(yy)+=(r(p)-mid)*laz(p); laz(yy)+=laz(p); laz(p)=0; } } inline void change(ll p,ll l,ll r,ll x,ll k)//修改长度和面积 { if(l<=l(p)&&r>=r(p)) { sum(p)+=(r(p)-l(p)+1)*k; len(p)+=(r(p)-l(p)+1)*x; tag(p)+=k;laz(p)+=x; return; } ll mid=(l(p)+r(p))>>1; if(tag(p)||laz(p))pushdown(p); if(l<=mid)change(zz,l,r,x,k); if(r>mid)change(yy,l,r,x,k); pushup(p); } inline jl merge(jl a,jl b) { a.sum+=b.sum; a.len+=b.len; return a; } inline jl ask(ll p,ll l,ll r) { if(l<=l(p)&&r>=r(p))return s[p]; ll mid=(l(p)+r(p))>>1; if(tag(p)||laz(p))pushdown(p); if(l>mid)return ask(yy,l,r); if(r<=mid)return ask(zz,l,r); return merge(ask(zz,l,r),ask(yy,l,r)); } signed main() { freopen("intersec.in","r",stdin); freopen("intersec.out","w",stdout); n=read();m=read(); W=read();L=read();L=max(L,W); for(ll i=1;i<=n;++i) { ll x,y,w1,w2; x=read();y=read()+1; w1=read();w2=read(); t[++cnt]=(wy){0,x,y,w2,1,-x}; t[++cnt]=(wy){0,w1,y,w2,-1,w1}; } for(ll i=1;i<=m;++i) { ll x,y,w1,w2; x=read();y=read()+1; w1=read();w2=read(); t[++cnt]=(wy){i,x,y,w2,0,-1}; t[++cnt]=(wy){i,w1,y,w2,0,1}; } sort(t+1,t+1+cnt); build(1,1,L); for(ll i=1;i<=cnt;++i) { if(!t[i].op) { //cout<<t[i].s1<<' '<<t[i].s2<<endl; change(1,t[i].s1,t[i].s2,t[i].len,t[i].s); //cout<<t[i].len<<' '<<t[i].s<<endl; } else { jl w=ask(1,t[i].s1,t[i].s2); ans[t[i].op]+=t[i].s*(w.len*t[i].x+w.sum); } } for(ll i=1;i<=m;++i)printf("%lld\n",ans[i]); return 0; }
30分爆搜 40分爆搜+剪枝从大到小搜搜到即return 即可得到40分。
另类的考虑状压 f[i][j] 表示集合i 此时余数是j的方案数 转移显然。复杂度2^n*n*10.可轻松通过40分。
100 显然 我们是无法状压的我们还需要利用取模的这个判定 我们还需要知道集合的使用情况 非常的不爽qwq
其实好像动态开数组应该也行吧 但是比max操作需要高精 所以还是歇菜。复杂度还是过高。
此时必然有一个 另类的判断条件 指的是 更强有力的判断是否是11的倍数。
于是有了一个 引理:一个数是11的倍数的充要条件是奇数位的和跟偶数位的和模11同余。(我显然是推不出来的。
这我很自闭... 但是证明其正确性还是可以的 设一个数字为 abcde *11 观察一下变化的特征 a(a+b)(c+b)(d+c)(e+d)e 考虑都不进位 那么显然。
如果有进位 那么要么奇项-10 偶项+1 要么偶项-10 奇项-1 所以是11的倍数 归纳可证结论正确。
那么我们就可以进行线性的dp了。还是不太会 考虑自己想一个。
这里放出题解 暂时咕了。