Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
「USACO 2020.12 Platinum」Cowmistry
Creato
2 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
I due testi sono identici
Non c'è alcuna differenza tra questi due testi
0 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
113 linee
Copia tutti
0 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
113 linee
Copia tutti
#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);
}
}
Diff salvati
Testo originale
Apri file
#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); }
Testo modificato
Apri file
#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); }
Trovare la differenza