HGOI-國慶七連測-day3
阿新 • • 發佈:2018-12-13
題解
講道理,真的很譴責這種掛著羊頭賣著恐龍肉的操作。標題寫著普及訓練難度結果是NOI/CTSC的題orz 真的爆零,我一道題都不會寫orz,出題人是江蘇高考415的dalao…
第一題——高考題(gaokao)
【題目描述】
- 給出二元組序列。
- 給出方程:
- 現在要求重新對二元組序列排序,使得序列T當中的最大的值最小。
-
這個真的是高考題…orz,那我高考的時候怕是要gg了…
-
其實你可以手動推一下:
-
總結規律你會發現其實
-
然後你會發現這個並沒有什麼用…
-
只能告訴你按照來排…
-
但這個還是錯解…但資料是錯誤解造出來的orz
-
相似題目(其實是一樣的)可以看這個洛谷2123,lzj大佬寫的是正解…
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
inline void fff(){
freopen("gaokao.in","r",stdin);
freopen("gaokao.out","w",stdout);
}
const int N=100010;
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
int n;
struct node{
LL t1,t2;
LL d;
bool operator < (const node x)const{
// if(d!=x.d) return d<x.d;
// if(d<=0) return t1<x.t1;
// return t2>x.t2;
return min(t1,x.t2)<min(t2,x.t1);
}
}a[N];
LL c[N];
int main(){
// fff();
int T;
cin>>T;
while(T--){
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
n=read();
for(int i=1;i<=n;i++){
a[i].t1=(LL)read();
a[i].t2=(LL)read();
if(a[i].t1>a[i].t2) a[i].d=1;
else if(a[i].t1<a[i].t2) a[i].d=-1;
else a[i].d=0;
}
sort(a+1,a+n+1);
LL sum=0;
for(int i=1;i<=n;i++){
sum+=a[i].t1;
c[i]=max(c[i-1],sum)+a[i].t2;
}
printf("%lld\n",c[n]);
}
}
第二題——高數題(gaoshu)
【題目描述】
- 在點權樹中,邊上存在顏色,規定所走路徑不能前後經過相鄰的顏色,求樹上合法路徑權值和。
- 唯一一個還能夠想想做法的題。和上一道和下一道的玄之又玄的做法完全不一樣。
- 三十分做法:暴力列舉開始節點,然後對於每一個節點模擬,最終結果由於出發節點和終點是等價的,所以結果除以2。最終複雜度
- 滿分做法:
- 假設根節點root,則從根節點出發向下進行路徑操作。對於每一顆子樹來說,他子樹下的節點的權值經過和是固定的。那麼維護下從dang下面節點延伸到當前節點的權值和與he合法途徑的條數。
- 顯然:
- 當前節點為根節點的所有合法路徑的權值和 = 之前深搜的所有子節點向上返回的邊數之和當前子節點返回的分數+ 之前深搜的所有子節點向上返回的分數之和 當前子節點返回的邊數+之前深搜的所有子節點向上返回的邊數之和當前子節點返回的邊數 當前點的權。
- 由於要考慮顏色,則需要將當前子樹的相同路徑的子樹進行“合併操作”。
- 然後就可以求出解了orz。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
const int N=300010;
inline void fff(){
freopen("gaoshu.in","r",stdin);
freopen("gaoshu.out","w",stdout);
}
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
int n;
int a[N],d[N];
struct Edge{
int from,to,color;
};
vector<Edge> edge;
vector<int> G[N];
map<int,pair<LL,LL>> tt[N];
bool visited[N];
bool cmp1(int i,int j){
return edge[i].color<edge[j].color;
}
LL num[N],val[N];
LL ans;
void dfs(int u,int fuck){
int siz=G[u].size();
visited[u]=true;
sort(G[u].begin(),G[u].end(),cmp1);
for(int i=0;i<siz;i++){
Edge &e=edge[G[u][i]];
if(visited[e.to]) continue;
dfs(e.to,e.color);
ans+=(num[u]-tt[u][e.color].first)*val[e.to]+(val[u]-tt[u][e.color].second)*num[e.to]+(num[u]-tt[u][e.color].first)*num[e.to]*a[u];
tt[u][e.color].first+=num[e.to];
tt[u][e.color].second+=val[e.to];
num[u]+=num[e.to];
val[u]+=val[e.to];
ans+