結果
| 問題 |
No.1649 Manhattan Square
|
| コンテスト | |
| ユーザー |
mugen_1337
|
| 提出日時 | 2021-08-14 20:49:02 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 600 ms / 3,000 ms |
| コード長 | 7,063 bytes |
| コンパイル時間 | 2,622 ms |
| コンパイル使用メモリ | 220,264 KB |
| 最終ジャッジ日時 | 2025-01-23 22:13:30 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 43 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}
struct IOSetup{
IOSetup(){
cin.tie(0);
ios::sync_with_stdio(0);
cout<<fixed<<setprecision(12);
}
} iosetup;
template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
for(T &x:v)is>>x;
return is;
}
template<ll Mod>
struct ModInt{
long long x;
ModInt():x(0){}
ModInt(long long y):x(y>=0?y%Mod:(Mod-(-y)%Mod)%Mod){}
ModInt &operator+=(const ModInt &p){
if((x+=p.x)>=Mod) x-=Mod;
return *this;
}
ModInt &operator-=(const ModInt &p){
if((x+=Mod-p.x)>=Mod)x-=Mod;
return *this;
}
ModInt &operator*=(const ModInt &p){
x=(int)(1ll*x*p.x%Mod);
return *this;
}
ModInt &operator/=(const ModInt &p){
(*this)*=p.inverse();
return *this;
}
ModInt operator-()const{return ModInt(-x);}
ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;}
ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;}
ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;}
ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;}
bool operator==(const ModInt &p)const{return x==p.x;}
bool operator!=(const ModInt &p)const{return x!=p.x;}
ModInt inverse()const{
int a=x,b=Mod,u=1,v=0,t;
while(b>0){
t=a/b;
swap(a-=t*b,b);swap(u-=t*v,v);
}
return ModInt(u);
}
ModInt pow(long long n)const{
ModInt ret(1),mul(x);
while(n>0){
if(n&1) ret*=mul;
mul*=mul;n>>=1;
}
return ret;
}
friend ostream &operator<<(ostream &os,const ModInt &p){return os<<p.x;}
friend istream &operator>>(istream &is,ModInt &a){long long t;is>>t;a=ModInt<Mod>(t);return (is);}
static int get_mod(){return Mod;}
};
using mint=ModInt<998244353>;
template<typename Monoid>
struct SegmentTree{
using F=function<Monoid(Monoid,Monoid)>;
private:
int sz;
vector<Monoid> seg;
Monoid query(int a,int b,int k,int l,int r){
if(a<=l and r<=b) return seg[k];
if(b<=l or r<=a) return M0;
Monoid L=query(a,b,2*k,l,(l+r)/2);
Monoid R=query(a,b,2*k+1,(l+r)/2,r);
return f(L,R);
}
template<typename C>
int find_first(int a,const C &check,Monoid &acc,int k,int l,int r){
if(k>=sz){
acc=f(acc,seg[k]);
if(check(acc)) return -1;
else return k-sz;
}
int m=(l+r)/2;
if(m<=a) return find_first(a,check,acc,2*k+1,m,r);
if(a<=l and check(f(acc,seg[k]))){
acc=f(acc,seg[k]);
return -1;
}
int x=find_first(a,check,acc,2*k+0,l,m);
if(x>=0) return x;
return find_first(a,check,acc,2*k+1,m,r);
}
template<typename C>
int find_last(int b,const C &check,Monoid &acc,int k,int l,int r){
if(k>=sz){
acc=f(acc,seg[k]);
if(check(acc)) return -1;
else return k-sz+1;//ここはfalse, +1した位置はtrue
}
int m=(l+r)/2;
if(b<=m) return find_last(b,check,acc,2*k,l,m);
if(r<=b and check(f(acc,seg[k]))){
acc=f(acc,seg[k]);
return -1;
}
int x=find_last(b,check,acc,2*k+1,m,r);
if(x>=0) return x;
return find_last(b,check,acc,2*k,l,m);
}
public:
F f;
Monoid M0;// モノイドの元
SegmentTree(int n,F f,Monoid M0):f(f),M0(M0){
sz=1;
while(sz<n)sz<<=1;
seg.assign(2*sz,M0);
}
void set(int k,Monoid x){
seg[k+sz]=x;
}
void build(){
for(int k=sz-1;k>0;k--) seg[k]=f(seg[2*k],seg[2*k+1]);
}
void update(int k,Monoid x){
k+=sz;
seg[k]=x;
k>>=1;
for(;k;k>>=1) seg[k]=f(seg[2*k],seg[2*k+1]);
}
Monoid query(int a,int b){
return query(a,b,1,0,sz);
}
Monoid operator[](const int &k)const{
return seg[k+sz];
}
// http://codeforces.com/contest/914/submission/107505449
// max x, check(query(a, x)) = true
template<typename C>
int find_first(int a,const C &check){
Monoid val=M0;
return find_first(a,check,val,1,0,sz);
}
// http://codeforces.com/contest/914/submission/107505582
// min x, check(query(x, b)) = true
template<typename C>
int find_last(int b,C &check){
Monoid val=M0;
return find_last(b,check,val,1,0,sz);
}
};
mint ManhattanSquareSum(vector<ll> x,vector<ll> y){
int N=(int)x.size();
mint ret=0;
{
mint sx=0,sy=0,sxx=0,syy=0;
for(int i=0;i<N;i++){
ret+=(mint)x[i]*x[i]*i+sxx-sx*x[i]*2;
ret+=(mint)y[i]*y[i]*i+syy-sy*y[i]*2;
sx+=x[i],sy+=y[i];
sxx+=(mint)x[i]*x[i];
syy+=(mint)y[i]*y[i];
}
}
{
vector<int> idx(N);
iota(begin(idx),end(idx),0);
sort(begin(idx),end(idx),[&](int i,int j){return x[i]>x[j];});
auto nx=x,ny=y;
for(int i=0;i<N;i++) nx[i]=x[idx[i]],ny[i]=y[idx[i]];
swap(x,nx);
swap(y,ny);
}
{
vector<int> yid(N),yp(N);
iota(begin(yid),end(yid),0);
sort(begin(yid),end(yid),[&](int i,int j){return y[i]<y[j];});
for(int i=0;i<N;i++) yp[yid[i]]=i;
using P=pair<mint,mint>;
auto segf=[&](P a,P b){
a.first+=b.first;
a.second+=b.second;
return a;
};
SegmentTree<P> sega(N,segf,P(0,0)),segb(N,segf,P(0,0));
for(int i=0;i<N;i++){
sega.set(yp[i],P(y[i],1));
segb.set(i,P(0,0));
}
sega.build();
segb.build();
for(int i=0;i<N;i++){
int j=yp[i];
auto l=sega.query(0,j);
auto r=sega.query(j+1,N);
mint add=mint(y[i])*l.second-l.first+r.first-mint(y[i])*r.second;
l=segb.query(0,j);
r=segb.query(j+1,N);
mint sub=mint(y[i])*l.second-l.first+r.first-mint(y[i])*r.second;
ret+=(add-sub)*x[i]*2;
sega.update(j,P(0,0));
segb.update(j,P(y[i],1));
}
}
return ret;
}
signed main(){
int N;cin>>N;
vector<ll> x(N),y(N);
rep(i,N) cin>>x[i]>>y[i];
cout<<ManhattanSquareSum(x,y)<<endl;
return 0;
}
mugen_1337