-(rmq)K - A Magic Lamp HDU - 3183
-(離散化+離線處理)L - Turing Tree HDU - 3333
-(dfs序圖建樹)M - Apple Tree POJ - 3321
-(lazypushdown最大值次大值)N - Gorgeous Sequence HDU - 5306
-(簡單題)P - The Child and Sequence CodeForces - 438D
(rmq)K - A Magic Lamp HDU - 3183
rmq入門(這裏dp指的是從i到j範圍內最小值最小數組從1開始)https://blog.csdn.net/weixin_43331783/article/details/95618122 題解:1中刪掉四個數留兩個數。所以第一個數字一定是1,5內的。所以在15之間搜尋最小值作爲第一個數假設位置爲x而第二個值肯定在x,6之間。所以用rmq維護一下最小值即可。#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
#define rmq_log2(x,val) while((1<<(x+1))<=val)x++;
const int maxn=1e3+3;
char a[maxn];
int dp[maxn][maxn];
int n;
int MIN(int a1,int c){
return a[a1]<=a[c]?a1:c;}
void rmq_init()
{
memset(dp,0, sizeof(dp));
for(int i=1;i<=n;i++)
dp[i][0]=i;//初始化
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=MIN(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int l,int r)
{
int k=0;
rmq_log2(k,r-l+1);
return MIN(dp[l][k],dp[r-(1<<k)+1][k]);
}
vector<int> v;
int main()
{
int m;
while(~scanf("%s%d",a+1,&m)) {
n = strlen(a+1);
v.clear();
rmq_init();
m=n-m;
int pos=1;
while (m--) {
pos = rmq(pos, n-m);
v.push_back(pos);
pos++;
}
int flag=0;
for(int i=0;i<v.size();i++){
if(flag){
cout<<a[v[i]];
}
else {
while(a[v[i]]=='0'&&i<v.size()) i++;
if(i<v.size()){cout<<a[v[i]];flag=1;}
}
}
if(flag==0)cout<<0<<endl;
else cout<<endl;
}
}
Turing Tree HDU - 3333
http://acm.hdu.edu.cn/showproblem.php?pid=3333題解鏈接:https://blog.csdn.net/T__TSZ/article/details/77529140
題解我懶得打。這個題解可以的。由於這裏重點在離散化所以下面的代碼直接是從代碼基礎改的。用離散模板改的。實測比原答案快。
#include<iostream>
#include<algorithm>
#include <vector>
#include<cstdio>
#include<cstring>
using namespace std;
#define ls o<<1
#define rs o<<1|1
#define lson L,mid,ls
#define rson mid+1,R,rs
#define mdzz int mid=(L+R)>>1;
int N,M;
long long tree[120005];
int s[30005];
int hashs[30005];
int vis[30005];
long long ans[100003];
struct node
{
int l,r,t;
bool operator <(const node &a)const
{
return a.r>r;
}
}q[200003];
void pushup(int o){
tree[o]=tree[ls]+tree[rs];
}
void update(int p,int L,int R,int o,int v){ //點修改
if(L==R){
tree[o]+=v;
return;
}
mdzz;
if(p<=mid) update(p,lson,v);
else update(p,rson,v);
pushup(o);
}
long long query(int l,int r,int L,int R,int o){//[l,r]區間詢問
if(r>=R&&l<=L) return tree[o];
mdzz;
long long ans=0;
if(l<=mid)
ans+=query(l,r,lson);
if(r>mid)
ans+=query(l,r,rson);
return ans;
}
vector<int> v;
int getid(int k)
{
return lower_bound(v.begin(),v.end(),k)-v.begin()+1;
}
int main()
{
int T;
scanf("%d",&T);
int a,b;
while(T--)
{
memset(vis,0,sizeof vis);
memset(tree,0,sizeof tree);
memset(hashs,0,sizeof hashs);
scanf("%d",&N);
for(int i=1;i<=N;i++){scanf("%d",&s[i]);
v.push_back(s[i]);}
scanf("%d",&M);
for(int i=1;i<=M;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].t=i;
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
sort(q+1,q+M+1);
int p=1;
for(int i=1;i<=M;i++)
{
while(p<=q[i].r)
{
int temp=getid(s[p]);
if(vis[temp])
update(vis[temp],1,N,1,-s[p]);
vis[temp]=p;
update(p,1,N,1,s[p]);
p++;
}
ans[q[i].t]=query(q[i].l,q[i].r,1,N,1);
}
for(int i=1;i<=M;i++)printf("%lld\n",ans[i]);
}
return 0;
}
(dfs序圖建樹)M - Apple Tree POJ - 3321
也是有趣的一道題展示懶得寫題解晚點再說。#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson k<<1, L, (L + R)>>1
#define rson k<<1|1, ((L + R)>>1) + 1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define dec(i, a, b) for(int i = a; i >= b; i --)
#define rmq_log2(x,val) while((1<<(x+1))<=val)x++;
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; }
typedef long long ll;
const int maxn = 100100;
const double eps = 1e-8;
ll MOD = 1000000007;
struct Edge{
int u,v,next;
}edge[maxn];
int cou;
int node[maxn];
void add(int u,int v){
edge[cou].u=u;
edge[cou].v=v;
edge[cou].next=node[u];
node[u]=cou++;
}
int st[(maxn<<2)+5];
void build(int o,int l,int r){
if(l==r){
st[o]=1;
return ;
}
int m=(l + r)>>1;
build(o<<1,l,m);
build((o<<1)|1,m+1,r);
st[o]=st[o<<1]+st[(o<<1)|1];
}
void update(int o,int l,int r,int ind){
if(l==r){
// if(st[o])st[o]=0;
// else st[o]=1;
// return;
st[o] = !st[o];
return;
}
int m=(l + r)>>1;
if(ind<=m){
update(o<<1,l,m,ind);
}
else{
update((o<<1)|1,m+1,r,ind);
}
st[o]=st[o<<1]+st[(o<<1)|1];
}
int query(int o,int l,int r,int ql,int qr){
// if(ql>r||qr<l) return 0;
if(ql<=l&&qr>=r) return st[o];
// int m=l+((r-l)>>1);
// int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr);
// return p1+p2;
int m = (l + r)>>1;
int ans = 0;
if(ql <= m)ans += query(o<<1,l,m,ql,qr);
if(qr > m)ans += query((o<<1)|1,m+1,r,ql,qr);
return ans;
}
int news;
int so[maxn][2];
void dfs(int now){
news++;
so[now][0]=news;
for(int i=node[now];i!=-1;i=edge[i].next){
dfs(edge[i].v);
}
so[now][1]=news;
}
int main() {
int n;
while (~scanf("%d", &n)) {
if (n == 0)break;/**/
int x, y;
cou = 0;
memset(node, -1, sizeof(node));//
for (int i = 1; i < n; i++) {
scanf("%d%d",&x,&y);
add(x, y);
}
memset(so, 0, sizeof(so));
news = 0;
dfs(1);
build(1, 1, n);
// cout<<1<<endl;
int m;
scanf("%d", &m);
char s[4];
int d;
// scanf("%s%d",op,&x);
while (m--) {
scanf("%s%d", s, &d);
// cout<<n<<endl;
if (s[0] == 'Q') {
printf("%d\n",query(1,1,n,so[d][0],so[d][1]));
} else if (s[0] == 'C') {
update(1, 1, n, so[d][0]);
}
}
}
return 0;
}
(最大值次大值)N - Gorgeous Sequence HDU - 5306
題解鏈接:https://blog.csdn.net/Nowara_Shinnosuke/article/details/72733223 操作:1.查詢區間最大值2.查詢區間和3。給一個數更新所有比他大的全部更新。前兩個爲常見操作不說了。最後一個如果按照常規操作要給定範圍節點都遍歷到不可,所以記錄最大次大值更新的時候及時返回(如果最大值都大於所給值不需要往下跑了或者節點範圍小於所給區間也暫時不用跑了)複雜度0(mlogn)
其實這道題沒那麼複雜,最大值次大值都是爲了lazy更新所用。就是一個需要用到lazy操作的樹。 這道題就用到了lazy。當這個節點的max值改變的時候就說明lazy賦值了(沒有明顯寫出lazy是啥)什麼是lazy呢?簡單來講有事才用,沒事不用。
比如說,假設有一個2的節點,連着一個3的子節點。從1開始更新,到2時發現符合條件不用更新了(這道題當節點區間小於所給區間並且最大值需要更新(所給值4最大值2)那麼把這個節點更新就可以了,不用更新到子節點)那麼3就不走過去了。
但是如果有一天要更新3的節點呢?這時候如果只把新的操作給3(所給值3原最大值2)那麼3的最大值是3嗎?不對應該是4.爲什麼會這樣剛剛lazy沒到這裏來。所以這個時候我們就需要pushdown也就是該用的時候就用。那麼有了這個當心操作來的時候會現在把之前的更新了(2變爲4)再去更新現在的。
同理,查詢也是。原本到2停了,現在我要查3的值那麼就需要先更新這樣得到4,不然的話就會得到2.
然而每個節點都需要pushdown嗎如果剛剛根本已經沒有在節點停住也就數lazy爲0那就不用再pushdown了。所以pushdow先判斷一下lazy是否爲0(這道題稍微隱晦了一下,當最大隻改變的時候其實lazy就有之了爲什麼自己想一下不難。所以本質是相同的。)
正確代碼看連接。
以下爲我的代碼。re了不知道爲什麼,找太久bug了,先放過晚點再說。
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson rt<<1, l, m
#define rson rt<<1|1, m+1, r
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define dec(i, a, b) for(int i = a; i >= b; i --)
#define rmq_log2(x,val) while((1<<(x+1))<=val)x++;
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; }
typedef long long ll;
const int maxn = 100100;
const int Maxn=1e6+10;
const double eps = 1e-8;
ll MOD = 1000000007;
int Max[Maxn<<2],sec[Maxn<<2],num[Maxn<<2];
ll tree[Maxn<<2];
void spup(int rt,int val){//specialupdate
if(Max[rt]<=val) return;
tree[rt]-=1ll*num[rt]*(Max[rt]-val);
Max[rt]=val;
}//?
void pushdown(int rt){
spup(rt<<1,Max[rt]);
spup(rt<<1|1,Max[rt]);
}//?
void pushup(int rt){
// int l=rt<<1,r=rt<<1|1;
// sec[rt]=max(sec[l],sec[r]);
// if(Max[l]<Max[r]){
// Max[rt]=Max[r];
// sec[rt]=max(sec[rt],Max[l]);
// num[rt]=num[r];
// }
// else{
// Max[rt]=Max[l];
// sec[rt]=max(sec[rt],Max[r]);
// num[rt]=num[l];
// }
// tree[rt]=tree[l]+tree[r];
int l=rt<<1,r=rt<<1|1;
tree[rt]=tree[l]+tree[r];
sec[rt]=max(max(sec[l],sec[r]),Max[l]==Max[r]?0:min(Max[l],Max[r]));
Max[rt]=max(Max[l],Max[r]);
num[rt]=0;
if(Max[rt]==Max[l]) num[rt]+=num[l];
if(Max[rt]==Max[r]) num[rt]+=num[r];
}
void build(int rt,int l,int r){
sec[rt]=-1;
if(l==r){
scanf("%d",&Max[rt]);
tree[rt]=(ll)Max[rt];
num[rt]=1;
return ;
}
else{
int m=l+r>>1;
build(lson);
build(rson);
pushup(rt);
}
}
void update(int rt,int l,int r,int rl,int rr,int val){
if(val>=Max[rt]) return;
if(rl<=l&&r<=rr&&val>sec[rt]){
spup(rt,val);
return;
}
pushdown(rt);
int m=l+r>>1;
if(rl<=m){
update(lson,rl,rr,val);
}
if(m<rr){
update(rson,rl,rr,val);
}
pushup(rt);
}
ll qsum(int rt,int l,int r,int rl,int rr){
if(rl<=l&&rr>=r) return tree[rt];
pushdown(rt);
int m=l+r>>1;
ll ans=0;
if(l<=m){
ans+=qsum(lson,rl,rr);
}
if(r>m){
ans+=qsum(rson,rl,rr);
}
return ans;
}
int qmax(int rt,int l,int r,int rl,int rr){
if(rl<=l&&rr>=r) return Max[rt];
pushdown(rt);
int m=l+r>>1;
ll ans=0;
if(l<=m){
ans=max(ans,qsum(lson,rl,rr));
}
if(r>m){
ans=max(ans,qsum(rson,rl,rr));
}
return ans;
}
int main(){
int t,m,n;scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int a,b,c,d;
scanf("%d",&a);
if(a==0){
scanf("%d%d%d",&b,&c,&d);
update(1,1,n,b,c,d);
}
else if(a==1){
scanf("%d%d",&b,&c);
printf("%d\n",qmax(1,1,n,b,c));
}
else{
scanf("%d%d",&b,&c);
printf("%lld\n",qsum(1,1,n,b,c));
}
}
}
}
(簡單題)P - The Child and Sequence CodeForces - 438D
給一個序列 支持3種操作 1 u v 對於所有i u<=i<=v,輸出a[i]的和 2 u v t 對於所有i u<=i<=v a[i]=a[i]%t 3 u v 表示a[u]=v(將v賦值給a[u]) n,q<=1e5 a[i],t,v<=1e9#include <iostream>
#include <stdio.h>
using namespace std;
const int MAXM=1e6+10;//定義 MAXM 爲線段最大長度
typedef long long ll;
ll tree[(MAXM<<2)+5],mx[(MAXM<<2)+5];
#define lson ro<<1, l, m
#define rson ro<<1|1, m+1, r
void pushup(int ro){
tree[ro]=tree[ro<<1]+tree[ro<<1|1];
mx[ro]=max(mx[ro<<1],mx[ro<<1|1]);
};
void build(int ro,int l,int r){
if(l==r){
scanf("%lld",&tree[ro]);
mx[ro]=tree[ro];
return ;
}
else{
int m=l+r>>1;
build(lson);
build(rson);
pushup(ro);
}
}
void update(int ro,int l,int r,int rl,int rr,int mod){
if(rl<=l&&r<=rr){
if(mx[ro]<mod)return;
if(l==r) {
tree[ro] %= mod;
mx[ro] %= mod;
return;
}
}
int m=l+r>>1;
if(rl<=m){
update(lson,rl,rr,mod);
}
if(m<rr){
update(rson,rl,rr,mod);
}
pushup(ro);
}
void update1(int ro,int l,int r,int index,int val){
if(l==r){
tree[ro]=val;
mx[ro]=val;
return;
}
int m=l+r>>1;
if(index<=m){
update1(lson,index,val);
}
if(m<index){
update1(rson,index,val);
}
pushup(ro);
}
ll query(int ro,int l,int r,int rl,int rr){
if(rl<=l&&r<=rr) return tree[ro];
int m=l+r>>1;
ll ans=0;
if(rl<=m){
ans+=query(lson,rl,rr);
}
if(rr>m){
ans+=query(rson,rl,rr);
}
return ans;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--){
int op,u,v;
scanf("%d%d%d",&op,&u,&v);
if(op==1){
printf("%lld\n",query(1,1,n,u,v));
}
else if(op==2){
int mod;
scanf("%d",&mod);
update(1,1,n,u,v,mod);
}
else if(op==3){
update1(1,1,n,u,v);
}
}
}