結果
問題 | No.1649 Manhattan Square |
ユーザー |
![]() |
提出日時 | 2021-07-28 22:24:00 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 801 ms / 3,000 ms |
コード長 | 3,262 bytes |
コンパイル時間 | 4,512 ms |
コンパイル使用メモリ | 253,076 KB |
実行使用メモリ | 58,476 KB |
最終ジャッジ日時 | 2024-10-03 16:00:05 |
合計ジャッジ時間 | 32,696 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 43 |
ソースコード
//g++ 3.cpp -std=c++14 -O2 -I .#include <bits/stdc++.h>using namespace std;#include <atcoder/all>using namespace atcoder;using ll = long long;using ld = long double;using vi = vector<int>;using vvi = vector<vi>;using vll = vector<ll>;using vvll = vector<vll>;using vld = vector<ld>;using vvld = vector<vld>;#define fi first#define se second#define pb push_back#define pq_big(T) priority_queue<T,vector<T>,less<T>>#define pq_small(T) priority_queue<T,vector<T>,greater<T>>#define all(a) a.begin(),a.end()#define rep(i,start,end) for(ll i=start;i<(ll)(end);i++)#define per(i,start,end) for(ll i=start;i>=(ll)(end);i--)using mint = modint998244353;struct S{//y=i範囲の点の数,xの合計,yの合計,xyの合計int quant;mint sum_x;mint sum_y;mint sum_pro;};S op(S a,S b){return {a.quant+b.quant,a.sum_x+b.sum_x,a.sum_y+b.sum_y,a.sum_pro+b.sum_pro};}S e(){return {0,0,0,0};}//i = 0 to N-1 j = i+1 to N (a[i]-a[j])^2mint sum_differ(vll &a){int sz=a.size();mint res=0,sum=0;rep(i,0,sz){sum+=a[i];mint x=a[i]*a[i];x*=2*sz;res+=x;}sum*=sum;res-=2*sum;res/=2;return res;}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin>>n;vll x(n),y(n);vll val_x,val_y;rep(i,0,n){cin>>x[i]>>y[i];val_x.pb(x[i]);val_y.pb(y[i]);}sort(all(val_x));sort(all(val_y));unique(all(val_x));unique(all(val_y));map<ll,int> inv_x;map<ll,int> inv_y;rep(i,0,val_x.size()){inv_x[val_x[i]]=i;}rep(i,0,val_y.size()){inv_y[val_y[i]]=i;}//座圧後の点vector<pair<int,int>> point(n);rep(i,0,n){point[i].fi=inv_x[x[i]];point[i].se=inv_y[y[i]];}sort(all(point));//x_coordinate[i] := 座圧後にx座標がiとなる点の番号vvi x_coordinate(n+100);rep(i,0,n){x_coordinate[point[i].fi].pb(i);}mint ans=0;//左から平面走査//seg[i] := 座圧後にy座標がiとなる点についてのいろいろsegtree<S,op,e> seg(n+100);rep(i,0,n+100){if(x_coordinate[i].size()==0)continue;//寄与の計算と更新for(int num:x_coordinate[i]){int x=point[num].fi,y=point[num].se;mint ori_x=val_x[x],ori_y=val_y[y];S range=seg.prod(0,y);ans+=range.quant*ori_x*ori_y;ans-=ori_x*range.sum_y;ans-=ori_y*range.sum_x;ans+=range.sum_pro;S now=seg.get(y);now.quant++;now.sum_x+=ori_x;now.sum_y+=ori_y;now.sum_pro+=ori_x*ori_y;seg.set(y,now);}}//初期化rep(i,0,n+100){seg.set(i,e());}//右から平面走査per(i,n+99,0){if(x_coordinate[i].size()==0)continue;//寄与の計算と更新for(int num:x_coordinate[i]){int x=point[num].fi,y=point[num].se;mint ori_x=val_x[x],ori_y=val_y[y];S range=seg.prod(0,y);ans-=range.quant*ori_x*ori_y;ans+=ori_x*range.sum_y;ans+=ori_y*range.sum_x;ans-=range.sum_pro;S now=seg.get(y);now.quant++;now.sum_x+=ori_x;now.sum_y+=ori_y;now.sum_pro+=ori_x*ori_y;seg.set(y,now);}}ans*=2;ans+=sum_differ(x);ans+=sum_differ(y);cout<<ans.val()<<"\n";}