2025杭电暑期联赛(第三场)(持续更新)

1007

题意:划分n个区间。一个数属于某个区间则获得其区间的性质。问一共有多少个不同性质的点

思路:
很快想到了哈希,但是离散化出了问题

显然将区间端点离散化,并为每个区间赋哈希值。再通过差分,统计不同大小的数即可

要注意:1.差分是对l,r+1进行操作的,因此差分时要对r+1进行额外的离散化
2.统计时用set会TLE,请用vector+sort+unique获取答案

std::mt19937_64 rnd(std::random_device{}()); 
void solve(){
    int n;cin>>n;
    vector<int>b;
    vector<pii>a(n+1);
    rep(i,1,n){
        cin>>a[i].fi>>a[i].se;
        b.pb(a[i].fi);
        b.pb(a[i].se);
        b.pb(a[i].se+1);
    }
    sort(b.begin(),b.end());
    unordered_map<int,int>mp;
    b.erase(unique(b.begin(),b.end()),b.end());
    vector<ull>h(n+1);
    for(int i=1;i<=n;i++){
        h[i]=rnd();
    }
    for(int i=1;i<=n;i++){
        if(!mp.count(a[i].fi))mp[a[i].fi]=lower_bound(b.begin(),b.end(),a[i].fi)-b.begin()+1;
        if(!mp.count(a[i].se))mp[a[i].se]=lower_bound(b.begin(),b.end(),a[i].se)-b.begin()+1;
        if(!mp.count(a[i].se+1))mp[a[i].se+1]=lower_bound(b.begin(),b.end(),a[i].se+1)-b.begin()+1;
    }
    vector<ull>length(b.size()+10);
    rep(i,1,n){
        length[mp[a[i].fi]]^=h[i];
        length[mp[a[i].se]+1]^=h[i];
    }
    for(int i=1;i<=b.size()+5;i++){
        length[i]^=length[i-1];
    }
    vector<int>tj(b.size()+5);
    for(int i=0;i<=b.size()+1;i++){
        tj[i]=length[i];
    }
    sort(tj.begin(),tj.end());
    int len=unique(tj.begin(),tj.end())-tj.begin();
    cout<<len<<endl;
}

1002

题意:给定n个点的位置以及对应权值。计算(1<=i<=j<=n) sigma(1<=i,j<=n) ( a_i + a_j ) x max(|xi-xj|,|yi-yj|)
思路:
QQ_1753457772645

将每个点坐标转化为(x+y,x-y),则两点间的切比雪夫距离转化为曼哈顿距离

具体的,1/2 x (a_i+a_j) x (|(xi+yi)-(xj+yj)| + |(xi-yi)-(xi-yi)|)

推导公式 := (a_i+a_j) x|(xi+yi)-(xj+yj)| + (a_i+a_j) x|(xi-yi)-(xi-yi)|

对于前者

不妨按照x+y的大小升序排序,以便去掉绝对值

=>(a_i+a_j) x ((xj+yj) - (xi+yi))

=> sigma(1<=i<=n) ai x [-pre[i-1]+suf[i+1]+ (xi+yi) x(2i-n-1)](重点!!!)

通过排序+前后缀优化,将两点之间的问题转移到一个点上

x-y同理

注意取模,取模时减法要先减再+mod再取模

struct node{
  int x,y;
  int val;
};
int n;
int cal(vector<pii>&a){
      int ans=0;

      rep(i,1,n){
        ans=((ans%mod+a[i].se*a[i].fi%mod*(2*i-n-1)%mod)%mod)%mod;
      }

      vector<int>pre(n+1);
      vector<int>suf(n+2);
      rep(i,1,n)pre[i]=(pre[i-1]%mod+a[i].fi%mod)%mod;
      for(int i=n;i>=1;i--)suf[i]=(suf[i+1]%mod+a[i].fi%mod)%mod;
      
      rep(i,1,n){
          ans=(ans%mod-a[i].se*pre[i-1]%mod+a[i].se*suf[i+1]%mod)%mod;
      }
  

      return ans;
}
int ksm(int a,int b){
  int res=1;
  while(b){
    if(b&1)res=res*a%mod;
    a=a*a%mod;
    b>>=1;
  }
  return res%mod;
}
int inv(int k){
  return ksm(k,mod-2)%mod;
}
void solve(){
    cin>>n;
    vector<node>a(n+1);
    vector<pii>b(n+1);
    vector<pii>c(n+1);
    rep(i,1,n){
      cin>>a[i].x>>a[i].y>>a[i].val;
      b[i]={a[i].x+a[i].y,a[i].val};
      c[i]={a[i].x-a[i].y,a[i].val};
    }
    int ans=0;
    sort(b.begin()+1,b.end());
    sort(c.begin()+1,c.end());
    ans+=cal(b);ans%=mod;
    ans+=cal(c);ans%=mod;
    ans=(ans%mod+mod)%mod;
    cout<<(ans*inv(2)%mod)<<endl;
}
posted @ 2025-07-25 19:32  Marinaco  阅读(42)  评论(0)    收藏  举报
//雪花飘落效果