数据结构补充

P1972 [SDOI2009] HH的项链

求[l,r]区间中颜色的数量

#include<cstdio>
#include<algorithm>
#include<vector>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int N=1e6+5;
int c[N],ans,s;
int n,m,x,op,p[N],t[N],a[N],f[N],g[N];
int l[N],r[N];
vector<int> q[N],id[N];
int lowbit(int x){
	return x&(-x);
}
void add(int x,int y){
	x++;
	while (x<N) {
		c[x]+=y;
		x+=lowbit(x);
	}
}
int ask(int x){
	x++;
	s=0;
	while (x){
		s+=c[x];
		x-=lowbit(x);
	}
	return s;
}
int main(){
//	freopen("data.in","r",stdin);
	
	scanf("%d",&n);
	fo(i,1,n) scanf("%d",&a[i]);
	
	fo(i,1,n) {
		p[i]=t[a[i]];
		t[a[i]]=i;
	}

	scanf("%d",&m);
	fo(i,1,m){
		scanf("%d %d",&l[i],&r[i]);
		q[r[i]].push_back(l[i]-1);
		id[r[i]].push_back(i);
	}
	
	fo(i,1,n){
		add(p[i],1);
		f[i]=i;
//		printf("%d\n",f[i]);
		
		for (int j=0;j<(int)q[i].size();j++) {
			g[id[i][j]]=ask(q[i][j]);
		}
	}
	
	fo(i,1,m) {
		ans=g[i]-f[l[i]-1];
		printf("%d\n",ans);
	}
	return 0;
}

带修莫队

[国家集训队] 数颜色 / 维护队列

题目描述

墨墨购买了一套 N 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

  1. Q L R 代表询问你从第 L 支画笔到第 R 支画笔中共有几种不同颜色的画笔。

  2. R P C 把第 P 支画笔替换为颜色 C

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int N=1e6+5;
const int M=1e6+5;
int t,l[N],r[N],a[N],cnt[M],ans,n,m,pos[N],x,y;
int b[N],c[N],tot,z,d[N],e[N];
int o[N];
char op;
void R(int &x){
    int a=0;char c=getchar();
    for(;c<'0'||c>'9';c=getchar());
    for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
    x=a;
}
struct node{
	int l,r,t,id;
};
node q[N];
bool cmp(node a,node b){
	if (a.l/t!=b.l/t) return a.l/t<b.l/t;
	if (a.r/t!=b.r/t) return a.r/t<b.r/t;
	return a.t<b.t;
}
inline void del(int x){
	cnt[a[x]]--;
	if (!cnt[a[x]]) ans--;
}
inline void add(int x){
	cnt[a[x]]++;
	if (cnt[a[x]]==1) ans++;
}
int main(){
//	freopen("data.in","r",stdin);
	R(n); R(m);
	fo(i,1,n) R(a[i]);
	fo(i,1,n) e[i]=a[i];
	
	t=pow(n,1/3.0);
	t=t*t;
	
	tot=0;
	scanf("\n");
	fo(i,1,m) {
		scanf("%c %d %d\n",&op,&x,&y);
		
		if (op=='Q') {
	
			z++;
			q[z]=(node){x,y,tot,z};
		}
		else{
			tot++;
			b[tot]=x; 
			c[tot]=y;
			d[tot]=e[x];
			e[x]=y;
		}
	}
	
	sort(q+1,q+z+1,cmp);
	x=1; y=0; t=0; ans=0; 
	fo(i,1,z) {
		
		while (x<q[i].l) del(x++);
		while (y>q[i].r) del(y--);
		while (x>q[i].l) add(--x);
		while (y<q[i].r) add(++y);
		
		while (t<q[i].t) {
			t++;
			if (x<=b[t] && b[t]<=y) del(b[t]);
			a[b[t]]=c[t];
			if (x<=b[t] && b[t]<=y) add(b[t]);
		}
		
		while (t>q[i].t) {
			if (x<=b[t] && b[t]<=y) del(b[t]);
			a[b[t]]=d[t];
			if (x<=b[t] && b[t]<=y) add(b[t]);
			t--;
		}
		o[q[i].id]=ans;
	}
	fo(i,1,z) printf("%d\n",o[i]);
	return 0;
}

cdq分治

三维偏序

#include<bits/stdc++.h>
#define fo(i,a,b) for (register int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (register int (i)=(b);(i)>=(a);(i)--)
#define eb emplace_back
#define pi pair<ll,ll>
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc ((o<<1)|1)
#define A puts("Yes")
#define B puts("No")
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef double db;
const ll mo1=1e9+7;
const ll mo2=1e9+9;
const ll P=131;
const ll Q=13331;
const ll mo=998244353;
const int N=2e5+5;
int c[N],n,k,cnt[N];
ll f[N];

struct node{
	int x,y,z,cnt,ans;
};
node a[N],b[N];
bool operator == (const node &a,const node &b){
	return a.x==b.x && a.y==b.y && a.z==b.z;

}
bool cmp1(node a,node b){
	if (a.x!=b.x) return a.x<b.x;
	if (a.y!=b.y) return a.y<b.y;
	return a.z<b.z;
}
bool cmp2(node a,node b){
	if (a.y!=b.y) return a.y<b.y;
	return a.z<b.z;
}
int lowbit(int x){
	return x&(-x);
}
void upd(int x,int y){
	for (;x<N;x+=lowbit(x)) c[x]+=y;
}
int ask(int x){
	int s=0;
	for (;x;x-=lowbit(x)) s+=c[x];
	return s;
}
void solve(int l,int r){
	if (l==r) return;
	int m=(l+r)>>1;
	solve(l,m); solve(m+1,r);
	
	sort(a+l,a+m+1,cmp2);
	sort(a+m+1,a+r+1,cmp2);
	int i=l,j=m+1;
	
	while (j<=r) {
		while (i<=m && a[i].y<=a[j].y) {
			upd(a[i].z, a[i].cnt);
			i++;
		}
		a[j].ans+=ask(a[j].z);
		j++;
	}
	
	fo(j,l,i-1) upd(a[j].z,-a[j].cnt);
}
int main() {
//    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);
//	
	scanf("%d %d",&n,&k);
	fo(i,1,n) scanf("%d %d %d",&b[i].x, &b[i].y, &b[i].z);
	sort(b+1,b+n+1,cmp1);
	
	int tot=0;
	for (int i=1,j;i<=n;i=j+1) {
		j=i;
		while (j<n && b[i]==b[j+1]) {
			j++;
		}
		a[++tot]=b[i];
		a[tot].cnt=j-i+1;
	}
	
	solve(1,tot);
	
	fo(i,1,tot) f[a[i].ans+a[i].cnt-1]+=a[i].cnt;
	fo(i,0,n-1) printf("%lld\n",f[i]);
	
    return 0;
    


} 

回滚莫队

歴史の研究

题面翻译

题目描述

JOI 教授决定用如下的方法分析这些日记:

  • 选择日记中连续的几天 [L,R] 作为分析的时间段;

  • 定义事件 A 的重要度 WAA×TA,其中 TA 为该事件在区间 [L,R] 中出现的次数。

现在,您需要帮助教授求出所有事件中重要度最大的事件是哪个,并输出其重要度

#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
using ll = long long;
constexpr int N = 1e5 + 5;
int n, q;
int x[N], t[N], m;

struct Query {
  int l, r, id;
} Q[N];

int pos[N], L[N], R[N], sz, tot;
int cnt[N], __cnt[N];
ll ans[N];

bool cmp(const Query& A, const Query& B) {
  if (pos[A.l] == pos[B.l]) return A.r < B.r;
  return pos[A.l] < pos[B.l];
}

void build() {
  sz = sqrt(n);
  tot = n / sz;
  for (int i = 1; i <= tot; i++) {
    L[i] = (i - 1) * sz + 1;
    R[i] = i * sz;
  }
  if (R[tot] < n) {
    ++tot;
    L[tot] = R[tot - 1] + 1;
    R[tot] = n;
  }
}

void Add(int v, ll& Ans) {
  ++cnt[v];
  Ans = max(Ans, 1LL * cnt[v] * t[v]);
}

void Del(int v) { --cnt[v]; }

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin >> n >> q;
  for (int i = 1; i <= n; i++) cin >> x[i], t[++m] = x[i];
  for (int i = 1; i <= q; i++) cin >> Q[i].l >> Q[i].r, Q[i].id = i;

  build();

  // 对询问进行排序
  for (int i = 1; i <= tot; i++)
    for (int j = L[i]; j <= R[i]; j++) pos[j] = i;
  sort(Q + 1, Q + 1 + q, cmp);

  // 离散化
  sort(t + 1, t + 1 + m);
  m = unique(t + 1, t + 1 + m) - (t + 1);
  for (int i = 1; i <= n; i++) x[i] = lower_bound(t + 1, t + 1 + m, x[i]) - t;

  int l = 1, r = 0, last_block = 0, __l;
  ll Ans = 0, tmp;
  for (int i = 1; i <= q; i++) {
    // 询问的左右端点同属于一个块则暴力扫描回答
    if (pos[Q[i].l] == pos[Q[i].r]) {
      for (int j = Q[i].l; j <= Q[i].r; j++) ++__cnt[x[j]];
      for (int j = Q[i].l; j <= Q[i].r; j++)
        ans[Q[i].id] = max(ans[Q[i].id], 1LL * t[x[j]] * __cnt[x[j]]);
      for (int j = Q[i].l; j <= Q[i].r; j++) --__cnt[x[j]];
      continue;
    }

    // 访问到了新的块则重新初始化莫队区间
    if (pos[Q[i].l] != last_block) {
      while (r > R[pos[Q[i].l]]) Del(x[r]), --r;
      while (l < R[pos[Q[i].l]] + 1) Del(x[l]), ++l;
      Ans = 0;
      last_block = pos[Q[i].l];
    }

    // 扩展右端点
    while (r < Q[i].r) ++r, Add(x[r], Ans);
    __l = l;
    tmp = Ans;

    // 扩展左端点
    while (__l > Q[i].l) --__l, Add(x[__l], tmp);
    ans[Q[i].id] = tmp;

    // 回滚
    while (__l < l) Del(x[__l]), ++__l;
  }
  for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
  return 0;
}
posted @   gan_coder  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2023-10-24 P3708 koishi的数学题(取模转化减法)
2023-10-24 ARC126C - Maximize GCD(取模转化减法)
  1. 1 青春コンプレックス 結束バンド
  2. 2 ギターと孤独と蒼い惑星 結束バンド
  3. 3 星座になれたら 結束バンド
  4. 4 恋のうた (feat. 由崎司) 鬼頭明里
  5. 5 月と星空 カノエラナ
  6. 6 Cagayake!GIRLS[5人Ver.] (TV size Ver.) 桜高軽音部
  7. 7 不可思議のカルテ 不可思議のカルテ
  8. 8 優しさの理由 ChouCho
ギターと孤独と蒼い惑星 - 結束バンド
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : ZAQ

作曲 : 音羽-otoha-

编曲 : ak?kin

突然降る夕立 あぁ傘もないや嫌

突然下起的夕雨 让我受够自己没带雨伞

空のご機嫌なんか知らない

天空的心情如何又与我何干

季節の変わり目の服は 何着りゃいいんだろ

季节交替之时 该换上什么衣服呢

春と秋 どこいっちゃったんだよ

春天与秋天 究竟去了哪里呢

息も出来ない 情報の圧力

息も出来ない 情報の圧力

息も出来ない 情報の圧力

令人喘不过气来 信息时代的压力

めまいの螺旋だ わたしはどこにいる

在这眩晕的螺旋之中 我究竟身处何方

こんなに こんなに 息の音がするのに

明明有着那么多 那么多的呼吸声

変だね 世界の音がしない

奇怪的是 这世界却 悄然无声

足りない 足りない 誰にも気づかれない

足りない 足りない 誰にも気づかれない

足りない 足りない 誰にも気づかれない

还不够 还不够 我还未被任何人所注意

殴り書きみたいな音 出せない状態で叫んだよ

好似杂乱无章的音律 不成声地呐喊着

「ありのまま」なんて 誰に見せるんだ

「真实的自我」 又是为了让谁看见

馬鹿なわたしは歌うだけ

愚昧无知的我唯有放声高歌

ぶちまけちゃおうか 星に

倾诉一切吧 对那星辰

エリクサーに張り替える作業もなんとなくなんだ

エリクサーに張り替える作業もなんとなくなんだ

エリクサーに張り替える作業もなんとなくなんだ

即便换上伊利克斯琴弦 音色也不尽人意

欠けた爪を少し触る

轻抚那边缘缺损的指甲

半径300mmの体で 必死に嗚いてる

以这半径300mm的身躯拼命奏响吉他

音楽にとっちゃ ココが地球だな

对于音乐来说这副身躯便是地球啊

空気を握って 空を殴るよ

空気を握って 空を殴るよ

空気を握って 空を殴るよ

握紧空气 殴向天空

なんにも起きない わたしは無力さ

却无事发生 我是如此的无力啊

だけどさ その手で この鉄を弾いたら

但是啊 用这手弹起这铁弦时

何かが変わって見えた…ような。

就好像能看到有什么发生变化…一样啊。

眩しい 眩しい そんなに光るなよ

眩しい 眩しい そんなに光るなよ

眩しい 眩しい そんなに光るなよ

闪烁耀眼 光彩夺目 请不要如此明亮啊

わたしのダサい影が より色濃くなってしまうだろ

这不就只会让我的丑陋影子愈加明显吗

なんでこんな熱くなっちゃってんだ 止まんない

为何我内心会变得如此炽热 无法停止

馬鹿なわたしは歌うだけ

愚昧无知的我唯有放声高歌

うるさいんだって 心臓

鼓动愈加喧嚣的 心脏

蒼い惑星 ひとりぼっち

蒼い惑星 ひとりぼっち

蒼い惑星 ひとりぼっち

我在这蓝色星球上孤独一人

いっぱいの音を聞いてきた

聆听到了众多声音

回り続けて 幾億年

地球自转数亿年

一瞬でもいいから…ああ

所以一瞬也好啊…啊啊

聞いて

请聆听

聴けよ

聴けよ

聴けよ

聆听我的声音啊

わたし わたし わたしはここにいる

わたし わたし わたしはここにいる

わたし わたし わたしはここにいる

我啊 我啊 我就存在于此啊

殴り書きみたいな音 出せない状態で叫んだよ

好似杂乱无章的音律 不成声地呐喊着

なんかになりたい なりたい 何者かでいい

仅是想成为 想成为 无论什么人都好

馬鹿なわたしは歌うだけ

愚昧无知的我唯有放声高歌

ぶちまけちゃおうか 星に倾诉一切吧 对那星辰

点击右上角即可分享
微信分享提示