Diff
checker
文本
文本
图像
文档
Excel
文件夹
Legal
Enterprise
桌面版
定价
登录
下载 Diffchecker 桌面版
比较文本
查找两个文本文件之间的差异
工具
历史
实时编辑器
折叠未更改行
关闭换行
视图
拆分
统一
比对精度
智能
单词
字符
语法高亮
选择语法
忽略
文本转换
转到第一个差异
编辑输入
Diffchecker Desktop
运行Diffchecker最安全的方式。获取Diffchecker桌面应用:您的差异永远不会离开您的电脑!
获取桌面版
「USACO 2020.12 Platinum」Cowmistry
创建于
2年前
差异永不过期
清除
导出
分享
两个文本完全相同
这两个文本之间没有差异
0 删除
行
总计
删除
字符
总计
删除
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
113 行
全部复制
0 添加
行
总计
添加
字符
总计
添加
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
113 行
全部复制
#include<bits/stdc++.h>
#include<bits/stdc++.h>
using namespace std;
using namespace std;
typedef long long ll;
typedef long long ll;
typedef pair <int,int> Pii;
typedef pair <int,int> Pii;
#define mp make_pair
#define mp make_pair
#define pb push_back
#define pb push_back
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
char IO;
char IO;
int rd(){
int rd(){
int s=0;
int s=0;
while(!isdigit(IO=getchar()));
while(!isdigit(IO=getchar()));
do s=(s<<1)+(s<<3)+(IO^'0');
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
while(isdigit(IO=getchar()));
return s;
return s;
}
}
const int N=2e4+10,P=1e9+7,I2=(P+1)/2,I3=(P+1)/3,U=1<<30;
const int N=2e4+10,P=1e9+7,I2=(P+1)/2,I3=(P+1)/3,U=1<<30;
int n,m,k;
int n,m,k;
int L[N],R[N];
int L[N],R[N];
int Check(){
int Check(){
for(int i=k;i;i>>=1) if(~i&1) return 0;
for(int i=k;i;i>>=1) if(~i&1) return 0;
return 1;
return 1;
}
}
int D3(int n){ return 1ll*n*(n-1)/2%P*(n-2)%P*I3%P; }
int D3(int n){ return 1ll*n*(n-1)/2%P*(n-2)%P*I3%P; }
int D2(int n){ return 1ll*n*(n-1)/2%P; }
int D2(int n){ return 1ll*n*(n-1)/2%P; }
const int M=N*60;
const int M=N*60;
int s[M],ls[M],rs[M],t[M],cnt,rt;
int s[M],ls[M],rs[M],t[M],cnt,rt;
//在线段树上插入节点,打上标记,同时处理出size便于下面计算
//在线段树上插入节点,打上标记,同时处理出size便于下面计算
void Ins(int &p,int l,int r,int ql,int qr){
void Ins(int &p,int l,int r,int ql,int qr){
if(!p) p=++cnt;
if(!p) p=++cnt;
s[p]+=min(qr,r)-max(ql,l)+1;
s[p]+=min(qr,r)-max(ql,l)+1;
if(ql<=l && r<=qr) { t[p]=1; return; }
if(ql<=l && r<=qr) { t[p]=1; return; }
int mid=(l+r)>>1;
int mid=(l+r)>>1;
if(ql<=mid) Ins(ls[p],l,mid,ql,qr);
if(ql<=mid) Ins(ls[p],l,mid,ql,qr);
if(qr>mid) Ins(rs[p],mid+1,r,ql,qr);
if(qr>mid) Ins(rs[p],mid+1,r,ql,qr);
}
}
int ans;
int ans;
// O(1)求出m
// O(1)求出m
int Up(int k){ return 1<<(32-__builtin_clz(k)); }
int Up(int k){ return 1<<(32-__builtin_clz(k)); }
typedef vector <Pii> V;
typedef vector <Pii> V;
V Union(const V &A,const V &B){
V Union(const V &A,const V &B){
int p1=0,p2=0,s1=A.size(),s2=B.size();
int p1=0,p2=0,s1=A.size(),s2=B.size();
V R;
V R;
// 这里是否归并并不影响复杂度
// 这里是否归并并不影响复杂度
while(p1<s1 || p2<s2) {
while(p1<s1 || p2<s2) {
if(p1<s1 && (p2==s2||A[p1]<B[p2])) {
if(p1<s1 && (p2==s2||A[p1]<B[p2])) {
if(R.size() && R.back().first==A[p1].first) R.back().second+=A[p1].second;
if(R.size() && R.back().first==A[p1].first) R.back().second+=A[p1].second;
else R.pb(A[p1]);
else R.pb(A[p1]);
p1++;
p1++;
} else {
} else {
if(R.size() && R.back().first==B[p2].first) R.back().second+=B[p2].second;
if(R.size() && R.back().first==B[p2].first) R.back().second+=B[p2].second;
else R.pb(B[p2]);
else R.pb(B[p2]);
p2++;
p2++;
}
}
}
}
return R;
return R;
}
}
V Calc(int a,int b,int L,int k,int f1,int f2){
V Calc(int a,int b,int L,int k,int f1,int f2){
f1|=t[a],f2|=t[b];
f1|=t[a],f2|=t[b];
V Res;
V Res;
// 底层情况O(1)解决
// 底层情况O(1)解决
if(!f1 && !a) return Res;
if(!f1 && !a) return Res;
if(f2) return Res.pb(mp(k+1,f1?L:s[a])),Res;
if(f2) return Res.pb(mp(k+1,f1?L:s[a])),Res;
if(!b) return Res.pb(mp(0,f1?L:s[a])),Res;
if(!b) return Res.pb(mp(0,f1?L:s[a])),Res;
int m=Up(k);
int m=Up(k);
// L>m说明还要继续进行分裂
// L>m说明还要继续进行分裂
if(L>m) return Union(Calc(ls[a],ls[b],L/2,k,f1,f2),Calc(rs[a],rs[b],L/2,k,f1,f2));
if(L>m) return Union(Calc(ls[a],ls[b],L/2,k,f1,f2),Calc(rs[a],rs[b],L/2,k,f1,f2));
// 进入降阶子问题,左查右,右查左
// 进入降阶子问题,左查右,右查左
k-=m/2;
k-=m/2;
V A=Calc(ls[a],rs[b],L/2,k,f1,f2);
V A=Calc(ls[a],rs[b],L/2,k,f1,f2);
for(auto &i:A) i.first+=f2?L/2:s[ls[b]];
for(auto &i:A) i.first+=f2?L/2:s[ls[b]];
V B=Calc(rs[a],ls[b],L/2,k,f1,f2);
V B=Calc(rs[a],ls[b],L/2,k,f1,f2);
for(auto &i:B) i.first+=f2?L/2:s[rs[b]];
for(auto &i:B) i.first+=f2?L/2:s[rs[b]];
return Union(A,B);
return Union(A,B);
}
}
int cm;
int cm;
// 第一次分裂
// 第一次分裂
void Solve(int p,int L){
void Solve(int p,int L){
if(!p) return;
if(!p) return;
// 完全覆盖的部分答案可以快速求出
// 完全覆盖的部分答案可以快速求出
if(t[p]) { cm+=L/m; return; }
if(t[p]) { cm+=L/m; return; }
// 已经完成分裂,此时进入第一层子问题
// 已经完成分裂,此时进入第一层子问题
if(L==m) {
if(L==m) {
// 贡献分为
// 贡献分为
// 左选3 , 右选 3
// 左选3 , 右选 3
ans=(ans+D3(s[ls[p]]))%P,ans=(ans+D3(s[rs[p]]))%P;
ans=(ans+D3(s[ls[p]]))%P,ans=(ans+D3(s[rs[p]]))%P;
// 左1,右2
// 左1,右2
V A=Calc(ls[p],rs[p],m/2,k-m/2,0,0);
V A=Calc(ls[p],rs[p],m/2,k-m/2,0,0);
// 左2,右1
// 左2,右1
V B=Calc(rs[p],ls[p],m/2,k-m/2,0,0);
V B=Calc(rs[p],ls[p],m/2,k-m/2,0,0);
for(auto i:A) ans=(ans+1ll*D2(i.first)*i.second)%P;
for(auto i:A) ans=(ans+1ll*D2(i.first)*i.second)%P;
for(auto i:B) ans=(ans+1ll*D2(i.first)*i.second)%P;
for(auto i:B) ans=(ans+1ll*D2(i.first)*i.second)%P;
return;
return;
}
}
Solve(ls[p],L/2),Solve(rs[p],L/2);
Solve(ls[p],L/2),Solve(rs[p],L/2);
}
}
int main(){
int main(){
n=rd(),k=rd();
n=rd(),k=rd();
rep(i,1,n) { int l=rd(),r=rd(); Ins(rt,0,U-1,l,r); }
rep(i,1,n) { int l=rd(),r=rd(); Ins(rt,0,U-1,l,r); }
m=Up(k),Solve(rt,U);
m=Up(k),Solve(rt,U);
// O(1)求得完全覆盖部分的答案
// O(1)求得完全覆盖部分的答案
int t=(2ll*D3(m/2)+1ll*D2(k-m/2+1)*m)%P;
int t=(2ll*D3(m/2)+1ll*D2(k-m/2+1)*m)%P;
ans=(ans+1ll*cm*t)%P;
ans=(ans+1ll*cm*t)%P;
printf("%d\n",ans);
printf("%d\n",ans);
}
}
已保存差异
原始文本
打开文件
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair <int,int> Pii; #define mp make_pair #define pb push_back #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i) char IO; int rd(){ int s=0; while(!isdigit(IO=getchar())); do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return s; } const int N=2e4+10,P=1e9+7,I2=(P+1)/2,I3=(P+1)/3,U=1<<30; int n,m,k; int L[N],R[N]; int Check(){ for(int i=k;i;i>>=1) if(~i&1) return 0; return 1; } int D3(int n){ return 1ll*n*(n-1)/2%P*(n-2)%P*I3%P; } int D2(int n){ return 1ll*n*(n-1)/2%P; } const int M=N*60; int s[M],ls[M],rs[M],t[M],cnt,rt; //在线段树上插入节点,打上标记,同时处理出size便于下面计算 void Ins(int &p,int l,int r,int ql,int qr){ if(!p) p=++cnt; s[p]+=min(qr,r)-max(ql,l)+1; if(ql<=l && r<=qr) { t[p]=1; return; } int mid=(l+r)>>1; if(ql<=mid) Ins(ls[p],l,mid,ql,qr); if(qr>mid) Ins(rs[p],mid+1,r,ql,qr); } int ans; // O(1)求出m int Up(int k){ return 1<<(32-__builtin_clz(k)); } typedef vector <Pii> V; V Union(const V &A,const V &B){ int p1=0,p2=0,s1=A.size(),s2=B.size(); V R; // 这里是否归并并不影响复杂度 while(p1<s1 || p2<s2) { if(p1<s1 && (p2==s2||A[p1]<B[p2])) { if(R.size() && R.back().first==A[p1].first) R.back().second+=A[p1].second; else R.pb(A[p1]); p1++; } else { if(R.size() && R.back().first==B[p2].first) R.back().second+=B[p2].second; else R.pb(B[p2]); p2++; } } return R; } V Calc(int a,int b,int L,int k,int f1,int f2){ f1|=t[a],f2|=t[b]; V Res; // 底层情况O(1)解决 if(!f1 && !a) return Res; if(f2) return Res.pb(mp(k+1,f1?L:s[a])),Res; if(!b) return Res.pb(mp(0,f1?L:s[a])),Res; int m=Up(k); // L>m说明还要继续进行分裂 if(L>m) return Union(Calc(ls[a],ls[b],L/2,k,f1,f2),Calc(rs[a],rs[b],L/2,k,f1,f2)); // 进入降阶子问题,左查右,右查左 k-=m/2; V A=Calc(ls[a],rs[b],L/2,k,f1,f2); for(auto &i:A) i.first+=f2?L/2:s[ls[b]]; V B=Calc(rs[a],ls[b],L/2,k,f1,f2); for(auto &i:B) i.first+=f2?L/2:s[rs[b]]; return Union(A,B); } int cm; // 第一次分裂 void Solve(int p,int L){ if(!p) return; // 完全覆盖的部分答案可以快速求出 if(t[p]) { cm+=L/m; return; } // 已经完成分裂,此时进入第一层子问题 if(L==m) { // 贡献分为 // 左选3 , 右选 3 ans=(ans+D3(s[ls[p]]))%P,ans=(ans+D3(s[rs[p]]))%P; // 左1,右2 V A=Calc(ls[p],rs[p],m/2,k-m/2,0,0); // 左2,右1 V B=Calc(rs[p],ls[p],m/2,k-m/2,0,0); for(auto i:A) ans=(ans+1ll*D2(i.first)*i.second)%P; for(auto i:B) ans=(ans+1ll*D2(i.first)*i.second)%P; return; } Solve(ls[p],L/2),Solve(rs[p],L/2); } int main(){ n=rd(),k=rd(); rep(i,1,n) { int l=rd(),r=rd(); Ins(rt,0,U-1,l,r); } m=Up(k),Solve(rt,U); // O(1)求得完全覆盖部分的答案 int t=(2ll*D3(m/2)+1ll*D2(k-m/2+1)*m)%P; ans=(ans+1ll*cm*t)%P; printf("%d\n",ans); }
更改后文本
打开文件
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair <int,int> Pii; #define mp make_pair #define pb push_back #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i) char IO; int rd(){ int s=0; while(!isdigit(IO=getchar())); do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return s; } const int N=2e4+10,P=1e9+7,I2=(P+1)/2,I3=(P+1)/3,U=1<<30; int n,m,k; int L[N],R[N]; int Check(){ for(int i=k;i;i>>=1) if(~i&1) return 0; return 1; } int D3(int n){ return 1ll*n*(n-1)/2%P*(n-2)%P*I3%P; } int D2(int n){ return 1ll*n*(n-1)/2%P; } const int M=N*60; int s[M],ls[M],rs[M],t[M],cnt,rt; //在线段树上插入节点,打上标记,同时处理出size便于下面计算 void Ins(int &p,int l,int r,int ql,int qr){ if(!p) p=++cnt; s[p]+=min(qr,r)-max(ql,l)+1; if(ql<=l && r<=qr) { t[p]=1; return; } int mid=(l+r)>>1; if(ql<=mid) Ins(ls[p],l,mid,ql,qr); if(qr>mid) Ins(rs[p],mid+1,r,ql,qr); } int ans; // O(1)求出m int Up(int k){ return 1<<(32-__builtin_clz(k)); } typedef vector <Pii> V; V Union(const V &A,const V &B){ int p1=0,p2=0,s1=A.size(),s2=B.size(); V R; // 这里是否归并并不影响复杂度 while(p1<s1 || p2<s2) { if(p1<s1 && (p2==s2||A[p1]<B[p2])) { if(R.size() && R.back().first==A[p1].first) R.back().second+=A[p1].second; else R.pb(A[p1]); p1++; } else { if(R.size() && R.back().first==B[p2].first) R.back().second+=B[p2].second; else R.pb(B[p2]); p2++; } } return R; } V Calc(int a,int b,int L,int k,int f1,int f2){ f1|=t[a],f2|=t[b]; V Res; // 底层情况O(1)解决 if(!f1 && !a) return Res; if(f2) return Res.pb(mp(k+1,f1?L:s[a])),Res; if(!b) return Res.pb(mp(0,f1?L:s[a])),Res; int m=Up(k); // L>m说明还要继续进行分裂 if(L>m) return Union(Calc(ls[a],ls[b],L/2,k,f1,f2),Calc(rs[a],rs[b],L/2,k,f1,f2)); // 进入降阶子问题,左查右,右查左 k-=m/2; V A=Calc(ls[a],rs[b],L/2,k,f1,f2); for(auto &i:A) i.first+=f2?L/2:s[ls[b]]; V B=Calc(rs[a],ls[b],L/2,k,f1,f2); for(auto &i:B) i.first+=f2?L/2:s[rs[b]]; return Union(A,B); } int cm; // 第一次分裂 void Solve(int p,int L){ if(!p) return; // 完全覆盖的部分答案可以快速求出 if(t[p]) { cm+=L/m; return; } // 已经完成分裂,此时进入第一层子问题 if(L==m) { // 贡献分为 // 左选3 , 右选 3 ans=(ans+D3(s[ls[p]]))%P,ans=(ans+D3(s[rs[p]]))%P; // 左1,右2 V A=Calc(ls[p],rs[p],m/2,k-m/2,0,0); // 左2,右1 V B=Calc(rs[p],ls[p],m/2,k-m/2,0,0); for(auto i:A) ans=(ans+1ll*D2(i.first)*i.second)%P; for(auto i:B) ans=(ans+1ll*D2(i.first)*i.second)%P; return; } Solve(ls[p],L/2),Solve(rs[p],L/2); } int main(){ n=rd(),k=rd(); rep(i,1,n) { int l=rd(),r=rd(); Ins(rt,0,U-1,l,r); } m=Up(k),Solve(rt,U); // O(1)求得完全覆盖部分的答案 int t=(2ll*D3(m/2)+1ll*D2(k-m/2+1)*m)%P; ans=(ans+1ll*cm*t)%P; printf("%d\n",ans); }
查找差异