日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【POI2015】KIN/Kinoman

發布時間:2025/7/25 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【POI2015】KIN/Kinoman 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

傳送門-洛谷
傳送門-bzoj

思路

考慮枚舉右端點。首先考慮應用前綴和,對于一個r,找一個最小的sum[l],把需要去掉的部分也放到sum[l]里。但這種做法是錯的….對于一個i,把他上一次出現的位置記做pre[i],每次把1到pre[i]之間所有區間的前綴和都加上一個w[i],但是不論如何區間中第一次出現的數是會被計算的,所以這樣不可以。
考慮另一種表示方式,對于每個遇到的 i ,把1到 i 這段都加上w[i],這樣的話sum[j]就表示的是 j 到 i 的連續區間和。然后考慮如何使得每個pre[i]之前的位置第i種電影的貢獻是0。重新考察剛剛那種做法為什么不對,不把那個多出來的次數當成第一個數,而是理解為每次區間中有一個重復的,我們會在求和的時候加一次,減去的時候減一次,相當于沒有減。于是這次我們考慮不讓他加上,只減去。于是每次遇到一個i,是把pre[i]+1到i加上w[i],把pre[pre[i]]+1到pre[i]減去,這樣使得任意pre[i]之前的都不會計算 i 的貢獻。
回顧我們的表示方法,他的好處是使得我們可以控制加減的范圍,而當使用前綴和的時候,我們無法控制每個值加在了哪里,只能進行減,于是無法操作。
如果還沒有理解的可以看看代碼

UPD:(套路部分)
對于一類允許離線,且對區間中數字出現個數有要求的題目,可以考慮按順序將點加入,然后適當對pre[u], pre[pre[u]]等進行修改操作

代碼

#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <math.h> #include <set> #define MAXN 1000050 #define INF (1<<28) #define LLINF (1LL<<40) #define LL long long using namespace std; int n, m, f[MAXN], w[MAXN], pre[MAXN], app[MAXN]; struct node{LL maxn, lazy; }t[MAXN<<2]; void push_down(int u){if(t[u].lazy){t[u<<1].lazy += t[u].lazy, t[u<<1].maxn += t[u].lazy;t[u<<1|1].lazy += t[u].lazy, t[u<<1|1].maxn += t[u].lazy;t[u].lazy = 0;} } void add(int u, int l, int r, int tl, int tr, int x){if(tl > tr) return;if(tl <= l && r <= tr){t[u].maxn += x, t[u].lazy += x;return;}push_down(u);int mid = (l+r)>>1;if(tl <= mid) add(u<<1, l, mid, tl, tr, x);if(mid < tr) add(u<<1|1, mid+1, r, tl, tr, x);t[u].maxn = max(t[u<<1].maxn, t[u<<1|1].maxn); } LL query(int u, int l, int r, int tl, int tr){if(tl <= l && r <= tr){return t[u].maxn;}push_down(u);int mid = (l+r)>>1; LL ret = 0;if(tl <= mid) ret = max(ret, query(u<<1, l, mid, tl, tr));if(mid < tr) ret = max(ret, query(u<<1|1, mid+1, r, tl, tr));return ret; } /* 共有m部電影,編號為1~m,第i部電影的好看值為w[i]。在n天之中(從1~n編號)每天會放映一部電影, 第i天放映的是第f[i]部。你可以選擇l,r(1<=l<=r<=n),并觀看第l,l+1,…,r天內所有的電影。 如果同一部電影你觀看多于一次,你會感到無聊,于是無法獲得這部電影的好看值。 所以你希望最大化觀看且僅觀看過一次的電影的好看值的總和。輸入輸出格式 輸入格式: 第一行兩個整數n,m(1<=m<=n<=1000000)。第二行包含n個整數f[1],f[2],…,fn。 第三行包含m個整數w[1],w[2],…,wm。輸出格式: 輸出觀看且僅觀看過一次的電影的好看值的總和的最大值。*/ int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%d", &f[i]);pre[i] = app[f[i]];app[f[i]] = i;}LL ans = 0;for(int i = 1; i <= m; i++) scanf("%d", &w[i]);for(int i = 1; i <= n; i++) {add(1, 1, n, pre[i]+1, i, w[f[i]]);add(1, 1, n, pre[pre[i]]+1, pre[i], -w[f[i]]);/*The following 2 lines are wrong!add(1, 1, n, 1, i, w[f[i]]);add(1, 1, n, 1, pre[i], -w[f[i]]);*/ans = max(ans, query(1, 1, n, 1, n));}printf("%lld", ans);return 0; }

轉載于:https://www.cnblogs.com/hychyc/p/9727469.html

總結

以上是生活随笔為你收集整理的【POI2015】KIN/Kinoman的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。