set&map
CodeForces 555C(set or 线段树)
题目大意:给一个巧克力,把副对角线(参照线代)下方的先都吃掉,然后每次给出一个询问,从对角线出发,要么向上,要么向左,吃到已经吃过的地方或者边缘为止,输出每次能吃多少小格巧克力。
思路:官方题解是线段树做得(我暂时还不会),然后在网上找到了一个超级简短的代码,是用set做的,但是我看了感觉有3个小时才基本看懂(汗。。。果然还是太弱了)。首先这个代码的离散化几乎没有多余的代码(佩服佩服),最开始看的时候有点搞不清楚方向。这个问题首先的突破点是:对于向上吃的操作,能够影响到其高度的之前的操作起始点应该是在这个操作的起始点右面的,而理解这个做法的最关键的一点是事实上能够影响的操作是最为靠近当前点的右面的点。也就是说当前这个点能够达到的最高点和最近右边的这个点能达到的最高点是一致的。如果右面这个点是向左,那么显然,如果右面这个点是向上,那么这个点得出的高度是考虑了更右面的所有点得出的,自然也适用于当前点。在代码里每次读入xy后,如果是向上,那么更新y,否则更新x,用set完成最近点的查找。
代码参照:http://blog.csdn.net/u011580493/article/details/46701113
又及:在cf的网站上看了下代码,个个都短得可以。。。。基本都是set和map,,没几个用线段树的。。。。。
#include<bits/stdc++.h> #define pb push_back using namespace std; typedef long long ll; typedef pair<int,int> P; const int maxv=2e5+50; int x[maxv],y[maxv]; set<P> s; set<P>::iterator it; int n,q; char ch[2]; int main(){ ///freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>q; s.insert(P(0,0)); s.insert(P(n+1,q+1)); for(int i=1;i<=q;i++){ scanf("%d%d%s",&x[i],&y[i],ch); if(ch[0]=='U'){ it=s.lower_bound(P(y[i],-1)); if(it->first>y[i]) it--; }else{ it=s.upper_bound(P(y[i],-1)); } if(it->first==y[i]){ puts("0"); continue; } s.insert(P(y[i],i)); if(ch[0]=='U'){ printf("%d\n",y[i]-y[it->second]); y[i]=y[it->second]; }else{ printf("%d\n",x[i]-x[it->second]); x[i]=x[it->second]; } } return 0; }
计划有时间写一下线段树版本。
题目:给出一棵树,每个节点有一种颜色,询问以每个节点为根的子树中数量最多的颜色的编号和是多少.
思路:直观的思路就是每个节点开一个map,记录颜色的数目,但是这样复杂度可以达到n^2logn,但是对于每个节点我们合并map的时候如果每次都把小的map合并到大的map里,那么每个节点的移动次数是logn的(因为每次移动map的大小至少增加为两倍),这样总复杂度就是nlog^2n.
#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-10) #define INF (0x3f3f3f3f) #define clr(x) memset((x),0,sizeof (x)) #define cp(a,b) memcpy((a),(b),sizeof (b)) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; const int maxn=1e5+300; int n; int c[maxn]; vector<int> G[maxn]; map<int,int> *mp[maxn]; map<int,int> M[maxn]; ll ans[maxn]; ll sum[maxn]; int cnt[maxn]; void dfs(int v,int f=-1){ for(int i=0;i<G[v].size();i++){ int u=G[v][i]; if(u==f) continue; dfs(u,v); if(mp[u]->size()>mp[v]->size()) swap(mp[u],mp[v]),swap(sum[u],sum[v]),swap(cnt[u],cnt[v]); if(cnt[u]>cnt[v]){ cnt[v]=cnt[u]; sum[v]=0; } map<int,int>::iterator it=mp[u]->begin(),it2; for(;it!=mp[u]->end();it++){ it2=mp[v]->find(it->fs); if(it2==mp[v]->end()){ (*mp[v])[it->fs]=it->se; if(it->se==cnt[v]) sum[v]+=it->fs; if(it->se>cnt[v]){ sum[v]=it->fs; cnt[v]=it->se; } }else{ it2->se+=it->se; if(it2->se==cnt[v]) sum[v]+=it2->fs; if(it2->se>cnt[v]){ sum[v]=it2->fs; cnt[v]=it2->se; } } } mp[u]->clear(); } ans[v]=sum[v]; } int main(){ IOS; //freopen("/home/slyfc/CppFiles/in","r",stdin); //freopen("/home/slyfc/CppFiles/out","w",stdout); for(int i=0;i<maxn;i++) mp[i]=&M[i]; cin>>n; for(int i=1;i<=n;i++) cin>>c[i]; for(int i=1;i<=n;i++){ (*mp[i])[c[i]]=1; sum[i]=c[i]; cnt[i]=1; } for(int i=0;i<n-1;i++){ int x,y; cin>>x>>y; G[x].pb(y); G[y].pb(x); } dfs(1); for(int i=1;i<=n;i++) cout<<ans[i]<<" "; return 0; }