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;
}
View Code

(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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code
posted @ 2016-10-21 19:19  v9fly  阅读(192)  评论(0编辑  收藏  举报