2016 ECJTU - STL
1、ECJTU-STL重挂 STL
2、总结:学长出的题,本来还想ak的,结果又被虐了。。。
3、标程和数据:http://pan.baidu.com/s/1qYzXY2K
01 水
02 水。题意:将1~n 全排列按字典序输出。
(1)dfs
//1002 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=10010,MAX=1000100; int vis[20],n,a[20],tot; void dfs(int m) { if(tot==n){ cout<<a[0]; F(i,1,tot)cout<<" "<<a[i]; cout<<endl; return ; } FF(i,1,n){ if(!vis[i]){ vis[i]=1;a[tot++]=i; dfs(i);vis[i]=0;tot--; } } } int main() { while(~scanf("%d",&n)) { mes(vis,0);tot=0; dfs(0); } return 0; }
(2)next_permutation()
#include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=10010,MAX=1000100; int main() { int n,a[15]; while(~scanf("%d",&n)){ a[1]=1; cout<<a[1]; FF(i,2,n) { a[i]=i; printf(" %d",i); }puts(""); while(next_permutation(a+1,a+1+n)) { cout<<a[1]; FF(i,2,n) printf(" %d",a[i]); puts(""); } } return 0; }
03 好题
1、题意:给你一个集合,n个整数,求出所有子集合的和的异或和。
2、总结:第一次用bitset。当要处理二进制位的有序集,每个位可能包含的是0(关)或1(开)的值,就应该可用bitset。
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #include<bitset> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=10010,MAX=10100; int main() { int n,x,sum; bitset<MAX >A(0); //关键就是,用i表示集合的和,A[i]的0,1开关值表示这个集合出现的次数奇偶 while(~scanf("%d",&n)){ A.reset(); A.set(0); sum=0; FF(i,1,n) { scanf("%d",&x); A^=(A<<x); //A上每一个位数i,都表示一个集合的和。移位x,表示在原有的集合上都加上x后的新情况。再与原来的集合异或,就表示加入x后的所有情况 sum+=x; } int ans=0; FF(i,1,sum) { if(A[i]) ans^=i; //最后这个位数的值a[i]为1,就表示这个集合和出现次数为奇数,就异或它。它为0,就表示出现次数为偶 } cout<<ans<<endl; } return 0; }
04 水,map应用。题意:n个点,求曼哈顿距离|xi-xj|+|yi-yj| 与欧几里得距离sqrt((xi-xj)^2+(yi-yj)^2) 相同的点对数
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #include<map> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=100100,MAX=1000100; int main() { int n; while(~scanf("%d",&n)) { map<pair<LL,LL>,int >S; map<LL ,int >A,B; LL x,y,sum=0; while(n--){ scanf("%lld%lld",&x,&y); sum+=(A[x]+B[y]); sum-=S[make_pair(x,y)]; S[make_pair(x,y)]++; A[x]++;B[y]++; } cout<<sum<<endl; } return 0; }
05 好但很恶心的题, 双端队列,类似 HDU 5929 。题意:模拟栈操作。
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #include<stack> #include<vector> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long #define pb push_back using namespace std; const int N=550000,MAX=1000100; int a[N]; int main() { int t,n,x,flag,tot1,tot2; char str[15]; deque<int >DQ; scanf("%d",&t); FF(cas,1,t){ DQ.clear(); flag=0; tot1=((N>>1)-1),tot2=(N>>1); scanf("%d",&n); printf("Case #%d:\n",cas); while(n--){ scanf("%s",str); if(str[2]=='S'){ scanf("%d",&x); if(!flag){ if(!x)DQ.push_back(tot1); a[tot1--]=x; }else { if(!x)DQ.push_front(tot2); a[tot2++]=x; } } else if(str[1]=='O'){ if(!flag){ tot1++; if(!a[tot1])DQ.pop_back(); }else { tot2--; if(!a[tot2])DQ.pop_front(); } } else if(str[0]=='R'){ flag^=1; } else { scanf("%d",&x); if(DQ.empty()) puts("Invalid."); else if(DQ.size()<x) puts("Invalid."); else { deque<int >::iterator it; if(!flag){ it=DQ.end(); cout<<*(it-x)-tot1<<endl; }else { it=DQ.begin(); cout<<tot2-*(it+x-1)<<endl; } } } } } return 0; }
06 好题,优先队列。题意:给出一个字符串,输出第k小的连续子串
//1006 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; struct S { string a; int a_r; bool operator < (const S &s1) const{ return a>s1.a; } }; int main() { string str; int k,i,j; S m; priority_queue<S > Q; /* while(cin>>str){ scanf("%d",&k); while(!Q.empty()) Q.pop(); for(i=0;str[i];i++){ for(j=i;str[j];j++){ m.a=str.substr(i,j); //一开始先把所有的连续子串都压入,结果一直超内存,看了标程才发现可以简单地优化一下 Q.push(m); } } if(k>Q.size()) k=Q.size(); for(i=1;i<k;i++){ Q.pop(); } cout<<Q.top().a; printf("\n"); } */ S st; while(cin>>str){ scanf("%d",&k); while(!Q.empty()) Q.pop(); for(int i=0;str[i];i++) { st.a=str[i]; st.a_r=i; Q.push(st); } while(!Q.empty()){ st=Q.top(); Q.pop(); //cout<<st.a<<endl; k--; if(!k) { cout<<st.a<<endl; break; } if(str[st.a_r+1]){ st.a+=str[st.a_r+1]; st.a_r++; Q.push(st); } } if(k)puts("No such line."); } return 0; }
07 set.lower_bound()函数。 题意:给你两个长度相同的序列A,B。求每一个Ai,在B序列中min(|A[i] - B[j]|) (1<=j<=i)是多少
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #include<set> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=100100,MAX=200100; int main() { int n; int a[N],b[N]; set<int >S; while(~scanf("%d",&n)) { S.clear(); S.insert(-MAX); S.insert(MAX); //先插入前后端,用lower_bound()时更方便一点 F(i,0,n) scanf("%d",&a[i]); F(i,0,n) scanf("%d",&b[i]); int pos,pre; set<int >::iterator it; F(i,0,n) { //scanf("%d",&b); //不能在这输入b[],题目是要全部输入后一起输出 S.insert(b[i]); it=S.lower_bound(a[i]); pos=*it; pre=*(--it); //迭代器只能++,--,不能+1,-1 printf("%d\n",min(pos-a[i],a[i]-pre)); } } return 0; }