P4145
題意:
思路:
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int n,q;
ll a[N];
struct Node{
int l,r;
ll sum,mx;
}tr[N<<2];
void pushup(int p){
tr[p].mx = max(tr[p<<1].mx,tr[p<<1|1].mx);
tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;
}
void build(int p,int l,int r){
tr[p].l = l,tr[p].r = r;
if(l == r){
tr[p].sum = tr[p].mx = a[l];
return;
}
int mid = l + r >> 1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
ll query(int p,int L,int R){
int l = tr[p].l,r = tr[p].r;
if(l >= L&& r <= R) return tr[p].sum;
int mid = l + r >> 1;
ll ans = 0;
if(L <= mid) ans += query(p<<1,L,R);
if(R > mid) ans += query(p<<1|1,L,R);
return ans;
}
void update(int p,int L,int R){
int l = tr[p].l,r = tr[p].r;
if(l == r){
tr[p].sum = tr[p].mx = sqrt(tr[p].sum);
return;
}
int mid = l + r >> 1;
if(L <= mid && tr[p<<1].mx > 1) update(p<<1,L,R);
if(R > mid && tr[p<<1|1].mx > 1) update(p<<1|1,L,R);
pushup(p);
}
int main(){
scanf("%d",&n);
for(int i = 1;i <= n;i++) scanf("%lld",a+i);
build(1,1,n);
scanf("%d",&q);
while(q--){
int op,l,r;scanf("%d%d%d",&op,&l,&r);
if(l > r) swap(l,r);
if(op == 0) update(1,l,r);
else printf("%lld\n",query(1,l,r));
}
return 0;
}
P2015
題意:
思路:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 105;
int n,m,head[N],idx;
struct Node{
int to,nex,w;
}e[N<<1];
void add_edge(int u,int v,int w){
e[idx].to = v;
e[idx].nex = head[u];
e[idx].w = w;
head[u] = idx++;
}
int f[N][N];//f(i,j)表示只考慮以i爲根節點的子樹並且揹包容量爲j的最大價值
void dfs(int u,int fa){
for(int i = head[u];~i;i = e[i].nex){
int v = e[i].to;
if(v == fa) continue;
dfs(v,u);
//倒序枚舉容量避免重複計算一個子節點的值
for(int j = m;j >= 1;j--){
//枚舉子節點選取邊的數量
for(int k = 0;k < j;k++){
f[u][j] = max(f[u][j],f[u][j-k-1]+f[v][k]+e[i].w);
}
}
}
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i = 1,u,v,w;i < n;i++){
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);add_edge(v,u,w);
}
dfs(1,0);
printf("%d\n",f[1][m]);
return 0;
}
P2195
題意:
思路:
+ ,)
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 3e5+10;
int n,m,q,fa[N],len;
inline int read() {
char ch=getchar();
int x=0,cf=1;
while(ch<'0'||ch>'9') {
if(ch=='-') cf=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*cf;
}
struct Node{
int to,nex;
}e[N<<1];
int head[N],idx,dima[N];
void add_edge(int u,int v){
e[idx].to = v;
e[idx].nex = head[u];
head[u] = idx++;
}
int find(int x){
return fa[x] == x?x:fa[x] = find(fa[x]);
}
int dfs(int u,int father){
int dist = 0;//表示以u往下走的最大長度
int d1 = 0,d2 = 0;//最大長度,次大長度
for(int i = head[u];~i;i=e[i].nex){
int v = e[i].to;
if(v == father) continue;
int d = dfs(v,u)+1;
dist = max(dist,d);
if(d >= d1) d2 = d1,d1 = d;
else if(d > d2) d2 = d;
}
len = max(len,d1+d2);
return dist;
}
void cal(int root){
len = 0;
dfs(root,0);
dima[root] = len;
}
int main(){
memset(head,-1,sizeof(head));
n = read(),m = read(),q = read();
for(int i = 1;i <= n;i++) fa[i] = i;
for(int i = 0,u,v;i < m;i++){
u = read(),v = read();
fa[find(u)] = find(v);
add_edge(u,v),add_edge(v,u);
}
for(int i = 1;i <= n;i++){
if(fa[i] != i) continue;
cal(i);//傳入根計算該樹的直徑
}
while(q--){
int op = read();
if(op == 1){
int x = read();
printf("%d\n",dima[find(x)]);
}else{
int x = read(),y = read();
x = find(x),y = find(y);
if(x==y) continue;
int ans = max(((dima[x]+1)>>1) + ((dima[y]+1)>>1) + 1,max(dima[x],dima[y]));
fa[find(x)] = y,dima[find(x)] = ans;
}
}
return 0;
}