結果
| 問題 |
No.1649 Manhattan Square
|
| コンテスト | |
| ユーザー |
蜜蜂
|
| 提出日時 | 2021-07-29 11:23:00 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 755 ms / 3,000 ms |
| コード長 | 2,824 bytes |
| コンパイル時間 | 4,645 ms |
| コンパイル使用メモリ | 249,220 KB |
| 実行使用メモリ | 58,420 KB |
| 最終ジャッジ日時 | 2024-10-03 16:02:13 |
| 合計ジャッジ時間 | 31,628 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| 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])^2
mint 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);
S range2=seg.prod(y+1,n+100);
ans+=range.quant*ori_x*ori_y;
ans-=ori_x*range.sum_y;
ans-=ori_y*range.sum_x;
ans+=range.sum_pro;
ans-=range2.quant*ori_x*ori_y;
ans+=ori_x*range2.sum_y;
ans+=ori_y*range2.sum_x;
ans-=range2.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";
}
蜜蜂