Diff
checker
Text
Text
Bilder
Dokumente
Excel
Ordner
Legal
Enterprise
Desktop-App
Preise
Einloggen
Diffchecker Desktop herunterladen
Texte vergleichen
Finde den Unterschied zwischen zwei Textdateien
Werkzeuge
Verlauf
Live-Editor
Gleiches ausblenden
Zeilenumbruch aus
Ansicht
Zweispaltig
Einspaltig
Vergleichsgenauigkeit
Intelligent
Wort
Zeichen
Syntaxhervorhebung
Syntax auswählen
Ignorieren
Text umwandeln
Zur ersten Änderung
Eingabe bearbeiten
Diffchecker Desktop
Der sicherste Weg, Diffchecker zu nutzen. Hol dir die Desktop-App: Deine Diffs verlassen nie deinen Computer!
Desktop holen
「USACO 2020.12 Platinum」Cowmistry
Erstellt
vor 2 Jahren
Diff läuft nie ab
Löschen
Exportieren
Teilen
Die beiden Texte sind identisch
Es gibt keinen Unterschied zwischen diesen beiden Texten
0 Entfernungen
Zeilen
Gesamt
Entfernt
Zeichen
Gesamt
Entfernt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
113 Zeilen
Kopieren
0 Hinzufügungen
Zeilen
Gesamt
Hinzugefügt
Zeichen
Gesamt
Hinzugefügt
Um diese Funktion weiterhin zu nutzen, aktualisiere auf
Diff
checker
Pro
Preise anzeigen
113 Zeilen
Kopieren
#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);
}
}
Gespeicherte Diffs
Originaltext
Datei öffnen
#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); }
Bearbeitung
Datei öffnen
#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); }
Unterschied finden