@sensitive-cs
        
        2017-03-03T14:41:55.000000Z
        字数 4860
        阅读 1017
    题解
VIRTUAL FRIENDS 
题意:略 
思路:并查集 
坑坑坑:bob 和 Bob不是一个名字,开始用tolower函数,我脑袋卡了,题也是。。。记住这个惨痛的教训,不要意淫一些事情找事做QAQ 
代码:
#include <stdio.h>#include <string.h>#include <map>#include <string>#include <ctype.h>using namespace std;map<string,int> mmp;int par[200005];int ran[200005];int sum[200005];int fin(int x){if (x == par[x])return x;elsereturn par[x] = fin(par[x]);}void unit(int x,int y){int rx = fin(x);int ry = fin(y);if (rx == ry) return;if (ran[rx] < ran[ry]){par[rx] = ry;sum[ry] += sum[rx];}else{par[ry] = rx;sum[rx] += sum[ry];if (ran[rx] == ran[ry]) ran[rx]++;}}int main(){int n;while (scanf("%d",&n) != EOF){for (int l = 1;l <= n;l++){int f;scanf("%d",&f);int k = 1;mmp.clear();memset(par,0,sizeof(par));memset(ran,0,sizeof(ran));memset(sum,0,sizeof(sum));for (int i = 1;i <= 200005;i++){sum[i] = 1;par[i] = i;}for (int o = 1;o <= f;o++){char a[25],b[25];scanf(" %s %s",a,b);if (!mmp[a])mmp[a] = k++;if (!mmp[b])mmp[b] = k++;int x = mmp[a],y = mmp[b];unit(x,y);int ans = 0;ans = fin(x);printf("%d\n",sum[ans]);}}}return 0;}
BAD HAIR-DAY 
题意: 
有一群羊,每一只羊有一定的高度,每只羊向右看可以看到严格小于她高度的羊的头,问每只羊一共可以看到多少羊头。 
思路: 
可以转换为每只羊可以被多少只羊看到。我们用一个栈来记录,每次入栈一个数,把这个数跟栈中的每一个数进行比较,直到遇到比她大的数为止,整个栈就成了一个单调栈。通过例子可以很清晰的明白。比如栈中有10 5 4,那么进去7的话,栈中最后的情况就是10和7,因为7比5和4大,5和4被遮住,所以就可以直接把5和4出栈,因为他们看不到7以后的羊了。 
坑!!!!:题目给出的范围是10的9次方,所以当时就没有注意和是可以超出整数范围的,所以要用long long。 
代码:
#include <stdio.h>#include <string.h>#include <stack>using namespace std;int a[80005];stack<int> sta;int main(){int n;memset(a,0,sizeof(a));while (!sta.empty())sta.pop();scanf("%d",&n);for (int i = 1;i <= n;i++)scanf("%d",&a[i]);sta.push(a[1]);int pos = 2;long long ans = 0;while (pos <= n){int t = a[pos];int in = sta.top();sta.pop();while (t >= in && !sta.empty()){in = sta.top();sta.pop();}if (t >= in){sta.push(t);pos++;continue;}sta.push(in);ans += sta.size();sta.push(t);pos++;}printf("%I64d\n",ans);return 0;}
SLIDING WINDOW 
题意:中文题意。 
思路:线段树水过 
坑:以后交poj,再也不用g++了 
代码:
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int maxn[4000005];int minn[4000005];int a[1000005];int ans[1000005][2];int min(int a,int b){return a >= b ? b : a;}int max(int a,int b){return a >= b ? a : b;}void pushupa(int rt){maxn[rt] = max(maxn[rt << 1],maxn[rt << 1|1]);}void pushupi(int rt){minn[rt] = min(minn[rt << 1],minn[rt << 1|1]);}void builda(int l,int r,int rt){if (l == r){maxn[rt] = a[l];return;}int m = (l+r) >> 1;builda(l,m,rt << 1);builda(m+1,r,rt << 1|1);pushupa(rt);}void buildi(int l,int r,int rt){if (l == r){minn[rt] = a[l];return;}int m = (l+r) >> 1;buildi(l,m,rt << 1);buildi(m+1,r,rt << 1|1);pushupi(rt);}int querya(int ll,int rr,int l,int r,int rt){if (ll <= l && r <= rr){return maxn[rt];}int m = (l+r) >> 1;int ans1 = -1000000000,ans2 = -1000000000;if (ll <= m) ans1 = querya(ll,rr,l,m,rt << 1);if (rr > m) ans2 = querya(ll,rr,m+1,r,rt << 1|1);return max(ans1,ans2);}int queryi(int ll,int rr,int l,int r,int rt){if (ll <= l && r <= rr){return minn[rt];}int m = (l+r) >> 1;int ans1 = 1000000000,ans2 = 1000000000;if (ll <= m) ans1 = queryi(ll,rr,l,m,rt << 1);if (rr > m) ans2 = queryi(ll,rr,m+1,r,rt << 1|1);return min(ans1,ans2);}int main(){int n,k;while (scanf("%d%d",&n,&k) != EOF){memset(a,0,sizeof(a));memset(maxn,0,sizeof(maxn));memset(minn,0,sizeof(minn));memset(ans,0,sizeof(ans));for (int i = 1;i <= n;i++)scanf("%d",&a[i]);builda(1,n,1);buildi(1,n,1);for (int i = 1;i <= n-k+1;i++){ans[i][0] = queryi(i,i+k-1,1,n,1);ans[i][1] = querya(i,i+k-1,1,n,1);}for (int i = 1;i <= n-k+1;i++)if (i == 1) printf("%d",ans[i][0]);else printf(" %d",ans[i][0]);printf("\n");for (int i = 1;i <= n-k+1;i++)if (i == 1) printf("%d",ans[i][1]);else printf(" %d",ans[i][1]);printf("\n");}return 0;}
Sumsets 
题意: 
Given S, a set of integers, find the largest d such that a + b + c = d 
where a, b, c, and d are distinct elements of S. 
思路: 
构造a+b,用二分,魔改pair,记录下标,因为数是不能重复的。 
代码:
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int a[1005];typedef pair<int,int> p;pair<p,int> pp[1000005];int b[1000005];bool cmp(pair<p,int> &a,pair<p,int> &b){return a.second < b.second;}int main(){int n;while (scanf("%d",&n) == 1 && n){memset(a,0,sizeof(a));memset(pp,0,sizeof(pp));memset(b,0,sizeof(b));for (int i = 0;i < n;i++)scanf("%d",&a[i]);sort(a,a+n);int sum = 0;for (int i = 0;i < n;i++)for (int j = 0;j < n;j++){if (j == i) continue;pp[sum].second = a[i] + a[j];pp[sum].first.first = i;pp[sum].first.second = j;sum++;}sort(pp,pp+sum,cmp);for (int i = 0;i < sum;i++)b[i] = pp[i].second;int mark = -1;for (int i = n-1;i >= 0;i--){for (int j = n - 1;j >= 0;j--){if (j == i) continue;int *pos = NULL;int key = a[i] - a[j];pos = lower_bound(b,b+sum,key);int r = pos - b;if (*pos == key && pos != b+sum && pp[r].first.second != i && pp[r].first.first != j && pp[r].first.second != j && pp[r].first.first != i){mark = i;break;}}if (mark != -1)break;}if (mark == -1) printf("no solution\n");else printf("%d\n",a[mark]);}return 0;}
Stripies 
题意: 
n只变形虫,他们中的任意两只遇到后质量会变成2*(sqrt(m1*m2)),问n只变形虫最后的质量最小是多少。 
思路: 
先把质量最大的拉出来续了,因为的续一次质量就会减少,我们要让质量越大的被续的次数越多才行,直到最后剩一个。而最理想的数据结构呢,就是优先队列了哦。 
代码:
#include <stdio.h>#include <string.h>#include <queue>#include <cmath>using namespace std;priority_queue<double> pp;int main(){int n;while (~scanf("%d",&n)){while (!pp.empty()) pp.pop();for (int i = 1;i <= n;i++){int t;scanf("%d",&t);pp.push(t);}while (pp.size() > 1){double x = pp.top();pp.pop();double y = pp.top();pp.pop();double k = 2*sqrt(x*y);pp.push(k);}double ans = pp.top();printf("%.3f\n",ans);}return 0;}